IO流:分为三大点,即
输入流:是按程序来说的。比如文件到程序。
输出流:程序到文件。
字节流:InputStream/OutputStream
这里有InputStream和OutputStream类型,关于这两种类型,他们的使用方法分别如下
对于InputStream来说:他用read来读入字节,比如read();read(byte[] b);read(byte[] b, int off, int len);
对于OutputStream来说:他用write写入字节,比如write(int b);write(byte[] b);write(byte[] b, int off, int len),
两种类型都需要用close()关闭;对于OutputStream,可以用flush();来进行冲刷,将数据写入。
对于IO流,有三种流,即基本流,包装流,字符流,下面对于这三种流做一下介绍
基本流/低级流/节点流
FileInputStream/FileOutputStream:
对于基本流来说,他其中构造中参数是介质,用一个例子来解释一下:
public class TestFISFOS { public static void main(String[] args) { InputStream is = null; OutputStream os = null; try { // 输入流文件必须存在。或者报文件找不到异常。 is = new FileInputStream(new File("d:\\a.txt")); int i = 0; while((i = is.read())!=-1){//用于输出a.txt中的内容 System.out.println((char)i); } byte[] b = new byte[10];//定义数组,求出a的长度 int len = is.read(b); System.out.println(len); // 输出流:自己会新建一个文件 // true表示追加 false表示覆盖 默认是false os = new FileOutputStream(new File("d:\\b.txt"),true);//创建一个文件夹b os.write(97);//在b.txt中写入a } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("文件找不到"); }catch (IOException e) { e.printStackTrace(); }finally{ try { is.close(); os.close(); } catch (IOException e) { e.printStackTrace(); } } }}
然后是包装流:包装流/高级流:对于包装流来说,包装流构造中参数是流。
BufferedInputStream/BufferedOutputStream:缓冲流,使用方法如下: FileInputStream fis = new FileInputStream(new File("d:\\src.rar")); BufferedInputStream bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream(new File("d:\\dest.rar")); BufferedOutputStream bos = new BufferedOutputStream(fos); 我们可以用他来实现文件的拷贝,用以下方法:int b = 0; byte[] arrByte = new byte[8*1024]; // 读源文件,将读入的每个字节依次写入目标文件即可。 while((b=fis.read(arrByte))!=-1){ fos.write(arrByte,0,b);//这里的0,b 将文件完整不多于的复制 } // 流操作的最后一定要关闭 fis.close(); fos.close();
对于flush();需要做一些解释,flush如果放在循环中,没有意义,相当于一个一个写入,
用以下程序说明:
int i = 0; while((i=bis.read())!=-1){ bos.write(i); // flush不要放在循环中,不然没意义,相当于一个字节一个字节的写。// bos.flush();// 冲刷缓冲区,强制将缓冲区中的内容写入文件 } // 如果缓冲区满了,自动写入文件 bos.flush();// 冲刷缓冲区,强制将缓冲区中的内容写入文件 bos.close();// close关闭之前,先flush。
DataInputStream/DataOutputStream:数据流
FileOutputStream fos = new FileOutputStream(new File("d:\\c.txt")); DataOutputStream dos = new DataOutputStream(fos); dos.writeDouble(3.14);//写入字节 dos.writeUTF("中国");// 将表示长度信息的两个字节写入输出流,后跟字符串 s 中每个字符的 UTF-8 修改版表示形式。 FileInputStream fis = new FileInputStream(new File("d:\\c.txt")); DataInputStream dis = new DataInputStream(fis); double d = dis.readDouble();//读入字节 String s = dis.readUTF();//读入一个已使用 UTF-8 修改版格式编码的字符串。
在此,由于写小数的方法太繁琐,介绍一种快速写小数的方法:
DataOutputStream out = new DataOutputStream( new BufferedOutputStream( new FileOutputStream(new File("d:\\c.txt"))));
接下来是字符流:
字符流:Writer/Reader
InputStreamReader/OutputStreamWriter与FileReader/FileWriter的区别
File file = new File("d:\\b.txt"); FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis,"gbk");// 字节转字符 // 对于汉字来说,gbk/gb2312占两个字节,utf-8占三个字节。 char i = (char)isr.read(); System.out.println(i); FileOutputStream fos = new FileOutputStream(file); OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk"); osw.write("中国"); for(int k=0;k<60000;k++){ osw.write(k); }// 系统默认编码 FileReader fr = new FileReader(file); char ch = (char) fr.read(); System.out.println(ch); // 区别 1.不能指定编码格式,按系统编码格式。2.不能包装其他流 FileWriter fw = new FileWriter(file); fw.write("一二三四五\r\n"); fw.write("六七八九十"); fw.close(); fr.close(); osw.close(); fis.close();
用OutputStreamWriter和InputStreamReader可以指定编码格式,但是用FileWriter和FileReader不能指定编码格式,只能用系统默认编码。
BufferedReader/BufferedWriter
File file = new File("d:\\b.txt"); FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); String str = null; str = br.readLine();//读取一个文本行。 System.out.println(str); FileOutputStream fos = new FileOutputStream(file); OutputStreamWriter osw = new OutputStreamWriter(fos); BufferedWriter bw = new BufferedWriter(osw); bw.write("一二三四五"); bw.newLine();// 新起一行。输出一个换行符 bw.write("六七八九十"); bw.flush();// 注意冲刷 bw.close(); isr.close();
我们可以利用此方法来写一个输入输出过程,
输入,Scanner
InputStream is = System.in; InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String s = br.readLine();//读取一个文本行。 System.out.println(s);
输出
PrintStream ps = new PrintStream(new File("d:\\b.txt"));// 包装流 System.out.println("打印到控制台"); System.setOut(ps);// 输入输出重定向 System.out.println("打印文件中"); ps.println("hello world");
使用setout后,将会把输入的信息写入文件中,另外,
PrintStream中的println方法经常和BufferedReader的readLine()配合使用。
对象序列化:
有时我们需要将内存堆区中的对象保存到文件中二进制数据,还需要将文件中的二进制数据再读到内存中
把对象转换成二进制数据(包括类的全名、属性名、属性值)——序列化
oos.writeObject(p1);// 对象序列化
把二进制数据还原为对象(根据类名创建对象,为指定属性名赋值)——反序列化
Person p2 = (Person) ois.readObject();// 对象反序列化
对象序列化也可采用这样的方法
while(true){ try { Person p = (Person) ois.readObject();// 对象反序列化 System.out.println(p); } catch (EOFException e) { System.out.println("读到了文件的末尾"); break; } }
可以用他来序列化多个对象,但是不建议使用
1. 一个对象想序列化,需要实现可序列化接口。Serializable接口,没有字段,没有方法,只是标志接口,用于说明对象可以被序列化了。
2. static或transient修饰的属性不被序列化。
static private int age; transient private String name;
1. 相关对象都需要实现Serializable接口。String也实现了该接口。
2. 多个对象的序列化借助于集合。
Listlist = new ArrayList (); Person p1 = new Person(20,"zhangfei"); Person p2 = new Person(30,"guanyu"); list.add(p1); list.add(p2); // 序列化整个集合 oos.writeObject(list);用以下方法输出:List perList = (List ) ois.readObject(); for(Person p : perList){ System.out.println(p); }