外观
字节输入流的操作
1.字节输入流的操作
1.创建流
private static void test1() {
// try-resource写法,jdk8以后支持
// 创建了字节流输入对象
try(InputStream inputStream = new FileInputStream("./test/test.txt")) {
// 读取字节流内容
// System.out.println(inputStream.read());
// 将读取的int数字转为char
// System.out.println((char)inputStream.read());
// 一次读取全部内容
int out;
while((out = inputStream.read()) != -1) {
System.out.print((char)out);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
2.操作流
1.inputStream.read()读取字节流内容的一个字节
循环遍历一次读取全部内容
2.read(byte[])使用byte数组批量读取
3.inputStream.skip(int n)跳过n个字节读取
4.read(byte[],offset,len)使用byte数组批量读取并跳过offset个数组元素存储len个字节
private static void test2() {
try(InputStream inputStream = new FileInputStream("./test/test.txt")) {
// read(byte[])使用byte数组批量读取
// 读取并存储10个字节
byte[] buffer = new byte[10];
// inputStream.read(buffer);
// read(byte[],offset,len)使用byte数组批量读取并跳过offset个数组元素存储len个字节
// inputStream.read(buffer, 2, 2);
// 跳过n个字节读取
inputStream.skip(2);
inputStream.read(buffer);
for (int i = 0; i < buffer.length; i++) {
System.out.print((char)buffer[i]);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
注:
1.每次按数组大小批量读取
2.返回数据表示成功读取到的字节数
3.数组不会被自动清空,上次读取到的数据依然存在
4.数据读取完毕返回-1
5.offset表示数组中存储的偏移值而不是读取指定的值,len表示读取长度
6.skip(long n)表示跳过n个字节开始读取
7.close()关闭流
8.输出流,字符流类似
2.字节输出流的操作
1.创建流
1.OutputStream outputStream = new FileOutputStream("./test/test1.txt") 文件不存在会自动创建,但不会创建路径
注:
1.构造方法参数可以是路径也可以是对应路径的文件对象
2.构造方法可以有两个参数,第二个为append的boolean值
true表示写入内容不会覆盖文件原本内容,false表示写入内容覆盖原本内容
默认为false
2.操作流
1.outputStream.write(int code)写入一个字节
2.outputStream.write(byte[] buffer)写入一个byte数组
3.outputStream.write(buffer,offset,len)写入并跳过offset个数组元素存储len个字节
4.outputStream.append(int code)在原来的内容上追加一个字符
5.outputStream.flush()强制将缓冲区内容写入到磁盘(安全写法)
6.outputStream.close()关闭流
private static void test1() {
try(OutputStream outputStream = new FileOutputStream("./test/test1.txt")) {
// 文件不存在会自动创建,但不会创建路径
// 写入一个字节
// outputStream.write('a');
// outputStream.write(65);
// 写入一个byte数组
byte[] buffer = {65,97,72,101};
// outputStream.write(buffer);
// 写入并跳过offset个数组元素存储len个字节
outputStream.write(buffer,2,2);
System.out.println("写入成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
3.字符输入流的操作
1.创建流
Reader reader = new FileReader("./test/test2.txt")
构造方法参数可以是路径也可以是对应路径的文件对象
2.操作流
1.reader.read()读取一个字符,结果为int
2.循环遍历一次读取全部内容
3.reader.read(char[] chs)以char数组形式读取文件内容
4.read(char[],offset,len)使用char数组批量读取并跳过offset个数组元素存储len个字节
5.reader.skip(int n)跳过n个字符读取
6.reader.close()关闭流
private static void test1() {
try(Reader reader = new FileReader("./test/test2.txt")) {
// 读取一个字符,结果为int
// System.out.println((char)reader.read());
// 读取全部
int out;
while((out = reader.read()) != -1) {
System.out.print((char)out);
}
// 以char数组形式读取文件内容
char[] chs = new char[15];
// 读取15个字符
// reader.read(chs);
// System.out.println(Arrays.toString(chs));
// read(char[],offset,len)使用char数组批量读取并跳过offset个数组元素存储len个字节
// reader.read(chs,2,5);
// 跳过n个字符读取
// reader.skip(3);
// reader.read(chs);
// System.out.println(Arrays.toString(chs));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
3.字符输出流的操作
1.创建流
Writer writer = new FileWriter("./test/test3.txt")
注:
1.构造方法参数可以是路径也可以是对应路径的文件对象
2.构造方法可以有两个参数,第二个为append的boolean值
true表示写入内容不会覆盖文件原本内容,false表示写入内容覆盖原本内容
默认为false
同字节流
2.操作流
1.writer.write('A')写入一个字符
2.writer.write(char[] chs)以字符数组形式写入
3.writer.write("你好")以字符串形式写入
4.writer.append('世')追加字符
5.writer.flush()强制从缓冲区写入磁盘
6.writer.close()关闭流
private static void test1() {
try(Writer writer = new FileWriter("./test/test3.txt")) {
// 写入一个字符
// writer.write('A');
// 以字符数组形式写入
char[] chs = {'哈','哈','哈'};
// writer.write(chs);
// 以字符串形式写入
writer.write("你好");
// 追加字符
writer.append('世');
writer.append('界');
writer.append((char) 183);
// 强制从缓冲区写入磁盘
writer.flush();
System.out.println("写入成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
4.流操作中的注意点
1.创建流对象之后在使用完流对象必须关闭流
/*
1.当我们new一个java流对象之后,不仅在计算机内存中创建了一个相应类的实例对象。而且,还占用了相应的系统资源,比如:文件句柄、端口、数据库连接等。在内存中的实例对象,当没有引用指向的时候,java垃圾收集器会按照相应的策略自动回收,但是却无法对系统资源进行释放。
2.我们需要主动调用close()方法释放java流对象。
3.在java7之后,可以使用try-with-resources语句来释放java流对象,从而避免了try-catch-finally语句的繁琐,尤其是在finally子句中,close()方法也会抛出异常。
一般来说,需要自己close的东西,都是用了虚拟机之外的资源,例如端口,显存,文件等,虚拟机无法通过垃圾回收释放这些资源,只能显式调用close方法来释放。比如释放占用的端口,文件句柄,网络操作数据库应用等。
4.一般来说,IO操作的底层就是这个步骤进行实现的,只要存在读写操作,无论使用到的是缓存IO,文件IO,还是块IO,都是需要和计算机内文件打交道的。清理计算机硬件上面的垃圾,虚拟机的本职能就没有这个任务。
gc()有下面的特性:
1)gc只能释放内存资源,而不能释放与内存无关资源。
2)gc回收具有不确定性,你根本不知道它什么时候会回收。
而对于需要程序员手动回收的资源往往具有这样的特点:
1)资源开销大,不用需要立即释放;
2)资源是系统唯一的,不释放会导致别的程序也无法使用该资源。
也就是说,对于具有这些特点的资源就必须保证不使用后能够立即释放出这部分资源,而不能把这么重要的事情交给一个具有不确定性不靠谱的gc来完成。
*/
2.为避免使用try-catch-finally语句的繁琐在使用流操作时流对象的创建一般在try-resourse中,无论有无手动关闭流都会自动关闭流,从而释放系统资源
try-resourse从JDK1.8开始支持
实质是编译器自动生成了try-catch-finally语句
1.try-with-resources语句是一个声明一个或多个资源的 try 语句。一个资源作为一个对象,必须在程序结束之后随之关闭。
2.try-with-resources语句确保在语句的最后每个资源都被关闭 。任何实现了 java.lang.AutoCloseable的对象, 包括所有实现了 java.io.Closeable 的对象, 都可以用作一个资源。