IO流学习总结
流的选择
流是操作输入输出数据的工具,那么对于不同的场景用什么样的流呢。按照下面的思路进行思考,可以让你快速的选择使用哪一个流。
1.输入or输出
输入:InputStream Reader
输出:OutputStream Writer
2.是否为纯文本
是:使用字符流Reader Writer
否:使用字节流 InputStream OutputStream
3.读写的目标
(1)文件:FileReader FileWriter FileInputStream FileOutputStream
(2)内存(字节数组):ByteStream不会被关闭,且不产生IO异常,可通过toCharArray
(3)流(管道流):PipedReader PipedOutputStream等,可以直接接收流,多用于多线程中,一个线程读,一个线程写
到了这里,已经可以创建基本的流对象了,例如:
FileWriter fr = new FileWriter("d://java//demo.txt");
fr.write("hello world!");//字符流可以直接写入字符串
FileOutputStream fos = new FileOutputStream("d://java//demo.txt");
fr.write("hello world!".getBytes());//字节流则只能写入字节数组
4.是否有额外功能
通过上面三步,已经可以基本确定使用哪个流对象,此时,若还需要额外的功能,则使用以下流对象对其进行装饰
(1)高效(使用缓冲区):BufferedReader BufferedOutputStream等,接收输入输出流
(2)多个输入流合并(序列流): SequenceInputStream接收1个枚举类型,包含多个InputStream,合并成1个InputStream
(3)操作对象:ObjectInputStream ObjectOutputStream接收1个字节流,使用writeObject和readObject方法读写对象,该对象需事先Serializable接口,该接口为对象的标记
(4)操作基本数据类型:DataStream接收1个字节流,可以直接读写如int型、char型的数据,例如DataInputStream.writeInt(age)
(5)回退:PushbackInputStream接收1个字节流,能使用unread()方法回退到读取某个字节前的状态,进行想要的操作,如在该字节前加入新的字节
(6)转换:InputStreamReader和OutputStreamWriter,分别接收1个字节流和1个字符流。转换流是字节流和字符流之间的桥梁,它可以将读取字节流并将其转换为字符流,或者将字符流转换成字节流方便写入。
(7)格式化输出:PrintWriter PrintStream(如System.out) ,分别接收1个字符流和1个字节流,后者比较常用。是输出动作最方便的输出流,可以输出任意数据类型的数据,System.out就是PrintStream的一个对象。
//装饰流的简写
BufferedWriter bufw = new BufferedWriter(new FileWriter("d://java//demo.txt"));
bufw.write("hello world!");
5.既能读又能写的流
同时具备读写功能的IO流:RandomAccessFile接收文件对象,可以进行读写,通过seek(pos)方法指定读写的指针位置,写入的新数据会覆盖对应位置数据,而不是覆盖整个文件。
6.总结
在开发过程中,操作文件的流较为常用,在不操作文件时,输入流常使用缓冲流,输出流常使用打印流。
流的使用
流的读写通常是结合在一起的,如从一个文件中读取数据,写入到领一个文件中,其代码如下
public static void demo1() {
FileReader fr = null;
FileWriter fw = null;
char[] buf = new char[1024*1024];//字节流要使用byte数组
try{
fr = new FileReader("a.txt");
fw = new FileWriter("b.txt");
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
fw.flush();
}
}catch(IOException e){
e.printStackTrace();
}finally{
try {
fr.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
由于流通常要操作文件,一旦文件出现问题,就会出现异常,所以所有流操作都需要用try()catch()捕获io异常,并且流的关闭动作应放在finally{}代码块里,以保证解除对资源的占用。
由于BufferedReader和BufferedWriter自带缓冲区,可以进行整行的读写,大大提高了效率,所以通常会使用它们对流进行修饰。下面这种流的读写方法比较推荐:
public static void demo0() {
BufferedReader bufr = null;
BufferedWriter bufw = null;
try{
bufr = new BufferedReader(new FileReader("a.txt"));
bufw = new BufferedWriter(new FileWriter("b.txt"));
String line = null;
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}catch(IOException e){
e.printStackTrace();
}finally{
try {
bufr.close();
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
编码问题
Utf-8中汉字为3个字节,gbk中汉子为2个字节
编码:String s = new String(buf,”gbk”);
解码:byte[] buf = str.getBytes(“ISO8859-1”);
可被流操作的集合-Properties
Propertoes类是一个持久的属性集,通常用于配置信息的持久化。其load()和store()方法接收1个输入流或输出流进行读写。
Properties的保存
FileOutputStream fos = null;
try{
Properties prop = new Properties();
prop.setProperty("name", "zhou");
fos = new FileOutputStream(new File("config.properties"));
prop.store(fos, "fileinfo");
}catch (IOException e) {
e.printStackTrace();
}
Properties的读取
File config = new File("config.properties");
Properties prop = new Properties();
try{
prop.load(new FileInputStream());
}catch (IOException e) {
e.printStackTrace();
}
String name = prop.getProperty("name");
各个流的介绍参考IO流详解可阅读http://blog.csdn.net/yczz/article/details/38761237