纸上得来终觉浅
1.Java IO流分类:
按照流向的不同(以程序为参照,流入程序的为输入流):输入流,输出流
根据处理数据的单位不同:字节流,字符流
根据角色不同:节点流(直接作用于文件),处理流
所有的流都是基于下面的抽象类:
2.这篇主要讲节点流(访问文件)和处理流,节点流主要是下面四个:
1)FileInputStream
2)FileOutputStream
3)FileReader
4)FileWriter
前两个类操作是以字节为单位,后两个类操作是以字符为单位;
5)所有的操作都可以用字节流, 即使是中文也可以(只是用字符流更好),下面是字节流操作中文的一个例子:
package roadArchitectWeb.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Test9 { public static void main(String[] args) { File file1 = new File("hello1.txt"); File file2 = new File("hello2.txt"); FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(file1); fileOutputStream = new FileOutputStream(file2); int length; byte[] b = new byte[1]; while((length=fileInputStream.read(b))!=-1){ fileOutputStream.write(b); // fileOutputStream.write("你好".getBytes("UTF-8")); // System.out.println("Test9.main():"+new String(b,"UTF-8")); } } catch(FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }hello1.txt:
ab中国得到的结果是:
hello2.txt:
ab中国3.解释2中的例子,为什么中文字符经过通过字节流输出到另一个文件还是中文:
1)首先要明确这样一个问题,所有的文件在其中的内容,在内容存在的时候就已经有了一种编码,并且存储在硬盘中,如上例中的hello1,假设它的编码是UTF-8;当用输入流一个字节一个字节的读的时候,并没有破化它存储在硬盘中的顺序,当把这些字节序放入到另一个文件中的时候,这个文件要解析它,我们可以指定一个编码方式对它进行解析,如果我在文件属性中设置了编码,假设为ASCII,它解析的结果肯定不是原来的汉字;如果指定的为UTF-8,就可以解析到。 所以结论是,字节流当然可以操作包含汉字的文本文件;
2)那为什么经常说不用字节流操作中文文本呢?
因为实际情况是:
A)在输入流中,假设源文件仍然是UTF-8的编码,用FileInputStream读了几个字节,并没有读完,这个时候
我并不知道读的这几个字节能不能正好组成几个汉字,因为源文件是UTF-8编码,汉字是三个字节;你可以说读取的时候三的倍数,如byte[] a = new byte[3],但如果源文件是汉字英文混合呢,所以操作起来要谨慎;
B)相比之下字符流就不会,如果使用FileReader:
采用FileReader一次读取的是汉字的UTF-8的三个字节,然后用一个Char来保存(这个时候UTF-8三个字节的汉字被转化为Unicode的两个字节),或者读取的是一个英文字符的UTF-8的一个字节,然后转化为Unicode的两个字节,也是用一个Char来保存;那么无论读到哪里,Char数组中始终保存的是完整的数据。这其实就是字符流唯一的好处。
示例如下:
fileReader = new FileReader(file1); fileWriter = new FileWriter(file2); char[] a = new char[1]; while((fileReader.read(a))!=-1){ fileWriter.write(a); }
注:输出流的问题,FileWriter输出的时候不能指定编码方式,会使用系统默认的编码方式;这个时候需要使用到转换流(可以指定编码格式),下面会讲到。
4.下面是一个字符串与字符编码的图表(转载自:http://blog.sina.com.cn/s/blog_5920510a0101ijj5.html):
总结:如果想使用字节流完全没有问题,可以在任何情况下使用,即使是文本文件。
5.处理流
BufferedReader,BufferedWriter,BufferedInputStream,BufferedOutputStream分别对应上面的四个类:
用法以BufferedReader,BufferedWriter为例(后面两个用法一样):
package roadArchitectWeb.Test; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Test9 { public static void main(String[] args) { File file1 = new File("hello1.txt"); File file2 = new File("hello2.txt"); FileReader fileReader = null; FileWriter fileWriter = null; BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { fileReader = new FileReader(file1); fileWriter = new FileWriter(file2); bufferedReader = new BufferedReader(fileReader); bufferedWriter = new BufferedWriter(fileWriter); String str; while((str=bufferedReader.readLine())!=null){ bufferedWriter.write(str); bufferedWriter.flush(); bufferedWriter.newLine(); System.out.println("Test9.main():"+str); } } catch(FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }6.转换流
上面说到了,字符流在输出的时候无法设定编码方式,只能使用系统默认的编码方式,下面使用转换流来进行编码转换:
package roadArchitectWeb.Test; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class Test9 { public static void main(String[] args) { File file1 = new File("hello1.txt"); File file2 = new File("hello2.txt"); FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; InputStreamReader inputStreamReader = null; OutputStreamWriter outputStreamWriter = null; BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { fileInputStream = new FileInputStream(file1); fileOutputStream = new FileOutputStream(file2); inputStreamReader = new InputStreamReader(fileInputStream,"GBK"); outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GBK"); bufferedReader = new BufferedReader(inputStreamReader); bufferedWriter = new BufferedWriter(outputStreamWriter); String str; while((str=bufferedReader.readLine())!=null){ bufferedWriter.write(str); bufferedWriter.flush(); bufferedWriter.newLine(); System.out.println("Test9.main():"+str); } } catch(FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { bufferedWriter.close(); outputStreamWriter.close(); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { bufferedReader.close(); inputStreamReader.close(); fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
同时转换流还有这样的功能: 即当知道文本是一种流的时候,还可以使用readline的功能。