欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

15_IO流,

来源: javaer 分享于  点击 44424 次 点评:86

15_IO流,


IO流 流的概念 流(stream)是指一连串流动字节/字符,按照先进先出的方式发送的信息的通道中。
数据源:流入通道中的数据的来源 目的地:流出通道的数据的目的地   输入流和输出流 数据源的数据流入程序的流称为输入流
  程序中的数据流出到目的地的流称为输出流
  流的分类
    InputStream/OutputStream inputstream 表示字节输入流,是所有字节输入流的抽象父类。提供了read/read(byte[] buf) 用于读取一个或者多个字节;close用于关闭输入流。   outputstream 表示字节输出流,是所有字节输出流的抽象父类。 FileInputStream FileInputStream 专门用于读取文件的字节输入流。可以用于读取文本性文件(存在编码)、图片音频视频等二进制文件。   一次读取一个字节
package cn.sxt01.fileinputstream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class Test01 { public static void main(String[] args) { // 需求:读取c.txt中的内容   File file = new File("d:\\javatest\\c.txt");   // 【1】构建输入流(管道) FileInputStream fis = null;   try { fis = new FileInputStream(file); System.out.println(fis); } catch (FileNotFoundException e) { e.printStackTrace(); }   // 【2】读取一个字节 int r = 0; try { r = fis.read(); } catch (IOException e) { e.printStackTrace(); }   System.out.println((char)r);   // 【3】关闭流 try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } }
read() 一次读取一个字节,如果已到达文件末尾,则返回 -1。   一次读取多个字节
package cn.sxt01.fileinputstream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; public class Test03 { public static void main(String[] args) { // 需求:读取c.txt中的内容   File file = new File("d:\\javatest\\c.txt");   // 【1】构建输入流(管道) FileInputStream fis = null;   try { fis = new FileInputStream(file); System.out.println(fis); } catch (FileNotFoundException e) { e.printStackTrace(); }   // 【2】读取一个字节 int len = 0; // 读取到缓冲区中的字节个数 byte[] buf = new byte[2]; // 字节缓冲区 StringBuilder sb = new StringBuilder(); try {   while( (len=fis.read(buf)) != -1 ) { String tmp = new String(buf,0,len); sb.append(tmp); }   } catch (IOException e) { e.printStackTrace(); }   System.out.println(sb);   // 【3】关闭流 try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } }
read(byte[] buf)一次读取多个字节到字节缓冲区,并返回读取的字节个数。     FileOutputStream   一次写一个字节
package cn.sxt01.fileouputstream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Test01 { public static void main(String[] args) { // 需求:写入helloworld 到d.txt中的内容   File file = new File("d:\\javatest\\d.txt");   // 【1】创建输出流(管道) FileOutputStream fos = null;   try { fos = new FileOutputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); }   //【2】写入信息到输出流 try { fos.write('h'); fos.write('e'); fos.write('l'); fos.write('l'); fos.write('o'); } catch (IOException e) { e.printStackTrace(); }   // 【3】刷新缓冲区 try { fos.flush(); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
  当调用write(int)方法时,把一个字节写入到输出流,输出流会立即把该字节写入文件中。 所以,如果不手动代用flush方法,信息也写入到文件中。   一次写多个字节(指定编码)
package cn.sxt01.fileouputstream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class Test02 { public static void main(String[] args) { // 需求:写入helloworld 到d.txt中的内容   File file = new File("d:\\javatest\\d.txt");   // 【1】创建输出流(管道) FileOutputStream fos = null;   try { fos = new FileOutputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); }   //【2】写入信息到输出流 try { String str = "hello world中国";   // 默认gbk编码 /*byte[] buf = str.getBytes(); fos.write(buf);*/   byte[] buf = str.getBytes("utf8"); fos.write(buf);   } catch (IOException e) { e.printStackTrace(); }   // 【3】刷新缓冲区 try { fos.flush(); // 【4】关闭文件 fos.close(); } catch (IOException e) { e.printStackTrace(); } } }
  write(byte[] buf)一次写入多个字节到输出流。注意,此时的字节流已经经过编码。默认是系统编码(win7:gbk)。 write(byte[] buf,offset,len) 一次写入buf中从offset开始,len个长度的字节到输出流。   综合案例: [1]把目录中的logo.jpg复制到工程中。 [2]请打印复制进度   Reader/Writer Reader 是字符输入流的抽象父类。提供了read()一次读取一个字符;read(char[] buf)一次多去多个字符到字符缓冲区。   Writer 是字符输出流的抽象父类。提供了 write()写入单个字符 write(char[] cbuf) 写入多个字符 write(String str) 写入字符串 FileReader FileReader是文件字符输入流,专门用于读取文本性文件。不能读取图片、音频、视频等二进制文件。   一次读取一个字符
package cn.sxt03.filereader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class Test01 { public static void main(String[] args) {   File file = new File("d:\\javatest\\d.txt");   // 【1】建立字符输入流 FileReader fr = null; try { fr = new FileReader(file); } catch (FileNotFoundException e) { e.printStackTrace(); }   // 【2】一次读取一个字符 int r = 0; try { /*r = fr.read(); r = fr.read(); r = fr.read(); r = fr.read(); r = fr.read(); r = fr.read();   System.out.println(r);*/   /* 中国abc\r\n 中国你好你好 */ StringBuilder sb = new StringBuilder(); while( (r=fr.read()) != -1 ) { sb.append((char)r); } System.out.println(sb);     } catch (IOException e) { e.printStackTrace(); }   // 【3】关闭输入流 try { fr.close(); } catch (IOException e) { e.printStackTrace(); }       } }
  一次读取多个字符
package cn.sxt03.filereader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Arrays; public class Test01 { public static void main(String[] args) {   File file = new File("d:\\javatest\\d.txt");   // 【1】建立字符输入流 FileReader fr = null; try { fr = new FileReader(file); } catch (FileNotFoundException e) { e.printStackTrace(); }   // 【2】一次读取多个字符 int len = 0; char[] cbuf = new char[2]; try {   /* len = fr.read(cbuf); len = fr.read(cbuf); len = fr.read(cbuf);   System.out.println(len); System.out.println(Arrays.toString(cbuf)); */   StringBuilder sb = new StringBuilder(); while( (len=fr.read(cbuf)) != -1) { sb.append(cbuf, 0, len); } System.out.println(sb);     } catch (IOException e) { e.printStackTrace(); }   // 【3】关闭输入流 try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } }
  FileWriter FileWriter 文件字符输出流,专门用于写入文本性文件。 通过FileWriter构造方法构造的对象写入文件时编码是系统默认编码(win7:gbk)。 由于写入的是字符,字符在写入时一定要经过编码,所以FileWriter内部有一个字符缓冲区用于存放待写入的字符,在调用flush时,FileWriter把字符缓冲区的字符编码成字节然后写入目标文件。  
package cn.sxt03.filewriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class Test01 { public static void main(String[] args) {   File file = new File("d:\\javatest\\e.txt");   FileWriter fw = null;   // 【1】建立输出流管道 try { /* * append:表示写入文件的方 * true:追加 false:覆 */ fw = new FileWriter(file,false); } catch (IOException e) { e.printStackTrace(); }   // 【2】写入 try {   // 写入一个字符 /*fw.write('中'); fw.write('国');*/ // 写入一个字符数组 /*char[] cbuf = {'中','国','\r','\n','a','b','c'}; fw.write(cbuf);*/   // 写入一个字符串 fw.write("中国abc");   } catch (IOException e) { e.printStackTrace(); }   // 【3】刷新 try { fw.flush(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } }
  思考:如何读取一个utf8编码的文本文件。   转换流 所谓转换流可以把字节流转化成字符流的转换流   InputStreamReader 是字节流通向字符流的桥梁,它使用指定的字符集读取字节并将其解码为字符。 OutputStreamWriter 是字符流通向字节流的桥梁,可使用指定的字符集将要写入流中的字符编码成字节   转换流工作原理
  以utf8编码写入文件
package cn.sxt04.outputstramwriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; public class Test01 { public static void main(String[] args) throws FileNotFoundException,IOException {   // 需求:写入 “中国abc” 以utf8编码写入 File file = new File("d:\\javatest\\g.txt");   FileOutputStream out = new FileOutputStream(file); OutputStreamWriter osw = new OutputStreamWriter(out, "utf8");   osw.write('中'); char[] cbuf = {'国','a'}; osw.write(cbuf);   osw.write("中国abc");   osw.flush(); osw.close(); } }
  以utf8编码读取文件
public class Test02 { public static void main(String[] args) throws FileNotFoundException,IOException {   // 需求:读取g.txt的内容 File file = new File("d:\\javatest\\g.txt");   FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis, "utf8");   /*int r = isr.read(); System.out.println((char)r);*/   char[] cbuf = new char[2]; int len = 0; StringBuilder sb = new StringBuilder(); while( (len=isr.read(cbuf)) != -1) { sb.append(cbuf,0,len); } System.out.println(sb);   } }
  思考:FileReader和InputStreamReader的关系?   注意:win7手动创建utf8编码的文件(utf8-bom) java程序写入的utf8文件不带bom
public class Test03 { public static void main(String[] args) throws FileNotFoundException,IOException {   // 需求:读取win手动创建的utf8编码的h.txt的内容 File file = new File("d:\\javatest\\h.txt");   FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis, "utf8");   /*int r = isr.read(); System.out.println((char)r);*/   char[] cbuf = new char[2]; int len = 0; StringBuilder sb = new StringBuilder(); while( (len=isr.read(cbuf)) != -1) { sb.append(cbuf,0,len); } System.out.println(sb);   } }
  BufferedReader/BufferedWriter FileReader 提供的读取字符的方式效率稍低,如果高效读写字符的方式,可以使用BufferedReader/BufferedWriter。   BufferedReader BufferedReader继承于Reader,专门用于高效的处理文本,提供了readLine方法用于一次读取一行文本。   把一首诗读取到控制台显示
package cn.sxt01.bufferedreader; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class Test01 { public static void main(String[] args) throws FileNotFoundException,IOException {   File file = new File("d:\\javatest\\i.txt");   // ctrl+t:查看类继承关系 FileReader reader = new FileReader(file); BufferedReader br = new BufferedReader(reader);   // 一次读取一行 /* String str = br.readLine(); str = br.readLine(); str = br.readLine(); str = br.readLine(); str = br.readLine(); System.out.println(str); */     String line; while( (line=br.readLine() ) != null) { System.out.println(line); }     br.close(); reader.close(); } }
    BufferedWriter BufferedWriter 是Writer的子类,专门用于高效的写入文本。提供了writer(String)和newLine()方法,写入完成后调用flush()刷新缓冲区。
package cn.sxt01.bufferedwriter; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class Test01 { public static void main(String[] args) throws FileNotFoundException,IOException {   // 需求:以utf8存入一首诗 File file = new File("d:\\javatest\\k.txt");   FileOutputStream out = new FileOutputStream(file); OutputStreamWriter osw = new OutputStreamWriter(out, "utf8");   BufferedWriter bw = new BufferedWriter(osw);   bw.write("床前明月光,"); bw.newLine();   bw.write("疑似地上霜。"); bw.newLine();   bw.flush();   bw.close(); osw.close(); out.close();   } }
  标准输入输出流
  标准输入流 java中用System.in表示标准输入流,属于InputStream字节输入流,标准输入设备(源):鼠标、键盘、手写板、麦克风、触摸屏等。     需求:从键盘输入一个字符并打印出来。
package cn.sxt02.inout; import java.io.IOException; import java.io.InputStream; public class Test01 { public static void main(String[] args) throws IOException {   // 从控制台输入一个字符并打印 InputStream in = System.in;   // 【1】一次读取一个字节:(输入/数据源是键盘) // int r = in.read(); // System.out.println((char)r);   // 【2】一次读取多个字节 byte[] buf = new byte[1024]; int len = 0; len = in.read(buf);   // 默认控制台是gbk编码 String str = new String(buf, 0, len); System.out.println(str); } }
标准输出流 java中用System.out表示标准输出流,属于PrintStream。标准的输出设备(源):显示器、显示屏   需求:从文件中读取文件内容并显示在标准输出设备上。
package cn.sxt02.inout; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.PrintStream; public class Test02 { public static void main(String[] args) throws IOException {   // 思考:为什么会乱码? File file = new java.io.File("d:\\javatest\\i.txt");   FileInputStream fis = new FileInputStream(file);   // 标准输出流(gbk) PrintStream ps = System.out;   int len = 0; byte[] buf = new byte[2]; while( (len=fis.read(buf)) != -1 ) { ps.write(buf, 0, len); }   fis.close();   } }
  通过打印流直接写入文件
package cn.sxt02.inout; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; public class Test05 { public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {   // 通过打印流写入数据到一个文件(gbk) /*File file = new File("d:\\javatest\\m.txt"); PrintStream ps = new PrintStream(file); ps.write('a'); ps.write('b');   ps.close();*/     // 通过打印流写入一个utf8编码的文件 File file = new File("d:\\javatest\\m1.txt"); PrintStream ps = new PrintStream(file,"utf8"); ps.println("abc中国");   ps.close();   } }
    需要flush的PrintStream
package cn.sxt02.inout; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; public class Test04 { public static void main(String[] args) {     PrintStream ps = System.out; ps.write('a'); ps.write('b');   ps.flush();   } }
  PrintStream称为打印字节流,继承于OutputStream,之前已经知道OutputStream写入文件时不需要flush。PrintStream的目的地是显示器,在PrintStream内部有个缓冲区,专门用于缓冲待输出的字节,结合显示器工作原理,当需要显示器显示待打印的字节时,需要手动调用flush方法,此时显示器才解码后显示。   测试自动刷新(C)
package cn.sxt02.inout; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; public class Test04 { public static void main(String[] args) throws IOException {   PrintStream ps = System.out; /*ps.write('a'); ps.write('b');*/   // 自动调用flush方 /*byte[] buf = {'a','b'}; ps.write(buf);*/   // 自动调用flush方 /*ps.write('a'); ps.write('b'); ps.write('\n');*/   // 自动调用flush方 ps.println("ab");   // sps.flush();   } }
    字符打印流 PrintWriter 专门用于向自定目的地(显示器、文件、浏览器)中输出大量字符。继承于Writer。除了write(char)/write(char[] cbuf),还提供了特有的print/println方法用于输出各位数据类型的字符。
public class Test01 { public static void main(String[] args) {   // 字符输出流 PrintWriter pw = new PrintWriter(System.out); pw.println("hello"); pw.println("中国");   pw.flush();   pw.close(); } }
  序列化 把(程序)内存中的数据保存到硬盘的过程就是序列化,也称为数据持久化。 当我们把硬盘中的数据再次读取到内存中时,这个过程就是反序列化。   Serializable接口   自定义类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化   需求:把一个对象序列化到d:\\javatest\\n1.txt  
package cn.sxt04.serializable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class Test01 { public static void main(String[] args) throws IOException {   User user = new User("001", "二狗", "123", 20);   /** * 思路: * 序列化:把对象个各个属性按照有规律的格式拼接成字符串,把字符串写入文件 * 反序列化:把文件中的字符串读取为内存中,按序列化格式把字符串拆开得到很多属性值,然后初始化对象 */ // String info = user.getId()+"-"+user.getName()+"-"+user.getPwd()+"-"+user.getAge(); // System.out.println(info);   File file = new File("d:\\javatest\\n1.sxt"); FileOutputStream out = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(out);   oos.writeObject(user);   oos.close(); out.close();   } }
  需求:把刚在序列化的对象反序列化
package cn.sxt04.serializable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class Test02 { public static void main(String[] args) throws IOException, ClassNotFoundException {   File file = new File("d:\\javatest\\n1.sxt"); FileInputStream in = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(in);   User user = (User) ois.readObject(); System.out.println(user);   } }
  序列号 当程序在升级过程中对源代码进行修改,新代码对之前的序列化文件进行反序列化存在一个InvalidClassException异常
Exception in thread "main" java.io.InvalidClassException: cn.sxt04.serializable.User; local class incompatible: stream classdesc serialVersionUID = 4281284299154400224, local class serialVersionUID = 8687762707351138232 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1876) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1745) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427) at cn.sxt04.serializable.Test02.main(Test02.java:19)
  如何解决? 始终保持本地类和序列化中文件的类的版本号一致。
[1]默认版本号,永远是1L [2]手动根据类的信息(属性、方法)生成一串数字。   版本号工作原理 如果自定义类没有添加任何序列化版本号,jvm自动添加一个序列化版本号,当修改源代码时,jvm自动升级该序列化版本号,此时导致和序列化到本地文件的类版本号不一致,反序列化必将失败,抛出InvalidClassException异常。   transient 关键字 在序列化过程中,存在一些字段序列化没有意义或一些敏感自动不许序列化,可以使用transient修饰。  
public class User implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String id; private String name; private transient String pwd; private int age; private String phone;
  其他流 DataInputStream/DataOutputStream

相关文章

    暂无相关文章
相关栏目:

用户点评