套路是如今比较流行的一个词,在最近的学习中,我也发现了很多编程方面的套路。今天就来谈谈Java文件操作中的一些套路。
Java文件操作的套路大体上可以分为三步走:1.声明IO流。2.使用流。3.关闭流。我们先来讨论比较简单的第一步和第三步。在这之前我们先分析一段初学者写的声明流和关闭流:
相信好多人都是这样做的,但考虑这样一个问题,如果在fis或fos进行读写的过程中目标文件被删或出现其他问题,那么程序会中断,并抛出异常,而此时fis和fos未被关闭,那么问题来了,这样合理吗?
所以相对合理的写法应该是这样的:
这就是第一步和第三步的套路:在声明IO流时声明在try外,实例化时在try内,而在关闭IO流时,在finally内去关闭,这样无论发生怎样的异常,fis和fos都一定会被关闭,从而保证安全性。
其它的流都可以套用这一套路:声明在try外,实例化时在try内,关闭在finally内。
接下来我们来重点讨论一下三步走中的第二步:
Java中的文件读取大体可分为按字节(byte)读取和按字符(char)读取,图一和图二都是按字节来读取的。而在按字节读取的时候,如果缓存区的大小设为单数字节的话,例如byte[5],那么在对中文进行读取的时候就会发生乱码,因为中文的编码是两个字节。所以在读取时最好设置缓冲区长度为偶数或者以字符的来读取。
按字节读取,图一图二以作示例,不再讨论;
按字符读取的话要借助于按字节读取,如例:
FileInputStream fis = null;
InputStreamReader reader = null;
fis = new FileInputStream("text.txt");
reader = new InputStreamReader(fis);
一个指向InputStreamReader的reader变量实例化的时候要以一个FileInputStream类型的变量作为构造函数的参数,接下来我们就可以设置一个字符数组作为缓冲区来进行读写了:
FileInputStream fis = null;
InputStreamReader reader = null;
FileWriter fw = null;
fis = new FileInputStream("text.txt");
reader = new InputStreamReader(fis);
fw = new FileWriter("result.txt");
char[] b = new char[512];
int len = 0;
while ((len = reader.read(b)) > 0){
fw.write(b, 0, len);
}
要注意的是在用什么方式读入的时候,就要用什么方式来写入,这里我用的InputStreamReader来读,用FileWriter来写入,还有其他的类也可以写入字符,可以灵活选择。
我们如果不想设置缓冲区的话,可以用BufferedReader类来进行一行的读取,这需要一个InputStreamReader类的变量来作为构造函数的参数,这里我们可以发现一个现象,InputStream,InputStreamReader,BufferedReader这三个类是有一定的实例化顺序的:InputStream>InputStreamReader>BufferedReader,从数据形式的角度来看是这样的byte-》char-》String,一个字符有一个或两个字节组成,一个字符串由多个字符组成,这样也就不难理解为啥这三个类要嵌套使用了。也正是因为这样,在关闭这三个流的时候要先关闭最底层的:InputStream<InputStreamReader<BufferedReader,这样就保证了其安全性。
其他要注意的问题:
1.在写入时默认覆盖写入,可以通过FileInputStream("test.txt",true);这种构造函数来在其结尾写入。
2.读的时候调用合理的组件可以加快读入的速度,在写的时候,可以以缓存的类来写入,有利于保护磁盘,如BufferedOutputStream。