文章目录
一、IO 流的体系结构
- 字节流:万能流,但是不能处理纯文本文件,因为会乱码。
抽象类
InputStream、OutputStream
子类
FileInputStream、FileOutputStream - 字符流:处理纯文本文件
抽象类
Reader、Writer
子类
FileReader、FileWriter
二、FileOutputStream 字节输出流
1. 构造方法
FileOutputStream(String name):输出流关联文件,参数是文件路径字符串。文件不存在自动创建。
FileOutputStream(File file) :输出流关联文件,参数是File对象
FileOutputStream(String name, boolean append):第二个参数,追加写入的开关
FileOutputStream(File file, boolean append) :第二个参数,追加写入的开关
2. 成员方法
write(int i):写出一个字节
write(byte[] bys):写出一个字节数组
write(byte[] bys, int off, int len):写出字节数组的一部分。开始索引,长度
FileOutputStream fos = new FileOutputStream("d:\\IoTest\\A.txt");
fos.write(97);//文件中显示:a
byte[] bytes = {97, 98, 99};
fos.write(bytes);//文件中显示:abc
fos.write("你好".getBytes());//文件中显示:你好
字符串转字节数组:字符串.getBytes()
注意:如果文件不存在,则自动创建;如果文件存在,先清空文件,再写操作。
如果追加写
FileOutputStream fos = new FileOutputStream("d:\\IoTest\\A.txt", true);
3.关流
- jdk7 之前
FileOutputStream fos = null;
try {
fos = new FileOutputStream("d:\\IoTest\\A.txt", true);
//System.out.println(10/0);
fos.write("abc".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
解释:
第一个catch捕获的是上面try里的异常(两个:构造、write)
第二个catch捕获的是finally里的异常(close)
- jdk7 之后
try (FileOutputStream fos = new FileOutputStream("d:\\IoTest\\A.txt", true);) {
fos.write("abcef".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
格式:try(需要调用close方法的对象){…}
不是随便的类,需要实现AutoCloseable的close()方法。
三、FileInputStream 字节输入流
构造方法
FileInputStream(String name):输入流关联文件,参数是文件路径字符串。文件不存在会报错!
FileInputStream(File file) :输入流关联文件,参数是File对象
注意事项:
文件不存在,会抛出FileNotFoundException 异常。(文件夹,拒绝访问)
成员方法
read():读取一个字节并返回,如果达到文件结尾返回-1
read(byte[] b):将读取到的字节,放入数组中,返回有效的字节长度,如果到达文件结尾返回-1
文件内容:ab
FileInputStream fis = new FileInputStream("D:\\IoTest\\A.txt");
int i = fis.read();
System.out.println(i);//97
int i1 = fis.read();
System.out.println(i1);//98
int i2 = fis.read();
System.out.println(i2);//-1
int i3 = fis.read();
System.out.println(i3);//-1
fis.close();
简单写法
FileInputStream fis = new FileInputStream("D:\\IoTest\\A.txt");
int i;
while ((i = fis.read()) != -1) {
System.out.print((char) i + " ");
}
fis.close();
可以强转为char
提高效率
把字节数组转为字符串
方式一:Arrays.toString(字节数组)
方式二:String的构造法方法public String(byte[] bytes, int offset, int len)
offset,起始位置偏移量,起始位置。
FileInputStream fis = new FileInputStream("D:\\IoTest\\A.txt");
byte[] bytes = new byte[2];
int len;
while ((len = fis.read(bytes)) != -1) {
String s = new String(bytes, 0, len);
System.out.print(s);//ababa
}
四、字节缓冲流
目的:大大提高效率。内置了字节数组,所以即使代码写的是一个一个读,也会按字节读取。一次读取/写入8192个字节。
加入构造方法
BufferedInputStream(InputStream in)
BufferedOutputStream(OutputStream in)
参数是接口,实际传参时传入new 实现类
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\IoTest\\A.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\IoTest\\B.txt"));
关流,只需关闭缓冲流,输入输出流也就关了
别的操作相同
copy最快的操作:自定义数组+缓冲流。不一定最快。有时自定义数组+普通流最快快。
自定义数组+缓冲流过程:一次性读取8192个装满缓冲区的数组,每次拷贝自定义数组8192长度字节数组,拷贝数组到缓冲区输出数组。
五、FileReader
乱码原因:一个中文汉字占3个字节,比如一次读取两个字节,就会出现乱码。
构造方法
FileReader(String filename)
FileReader(File file)
成员方法
public int read():读取单个字符
public int read(char[] cbuf):读取字符数组,返回读取到的有效字符个数
FileReader fr = new FileReader("D:\\IoTest\\A.txt");
int read;
while ((read = fr.read()) != -1) {
System.out.print((char) read);
}
FileReader fr = new FileReader("D:\\IoTest\\A.txt");
int len;
char[] chars = new char[2];
while ((len = fr.read(chars)) != -1) {
String s = new String(chars, 0, len);
System.out.print(s);
}
六、FileWriter
构造方法
FileWriter(String filename)
FileWriter(File file)
FileWriter(String filename, boolean append)
FileWriter(File file, boolean append)
成员方法
public void write(int c)
public void write(char[] cbuf)
public void write(char[] cbuf, int off, int len)
public void write(String str)
public void write(String str, int off, int len)
try (FileReader fr = new FileReader("D:\\IoTest\\A.txt");
FileWriter fw = new FileWriter("D:\\IoTest\\B.txt");) {
int len;
char[] chars = new char[2];
while ((len = fr.read(chars)) != -1) {
fw.write(chars, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
注意:字符输出流写出数据,需要调用flush或close方法,数据才会写出。
flush():刷出数据,刷出后可以继续写出。
close():关闭流释放资源,刷出数据,不可继续写出。
因为有个缓冲区,先写入缓冲区,调用flush/close,才写进文件中。