首页 > 代码库 > Java IO流

Java IO流

1.流的概念

Java采用流的机制来实现输入/输出。

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样,如下图:

输出流:

技术分享

输入流:

技术分享

 

2.Java输入输出流

技术分享

 

技术分享

技术分享

技术分享

技术分享

 

InputStream:输入字节流。继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位 byte[])。

  1. InputStream 是所有的输入字节流的父类,它是一个抽象类。

  2. ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据。

  3. ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。

Inputstream类中的常用方法: 

   (1) public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。

   (2) public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的 

   (3) public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。 

   (4) public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,

   (5) public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取 

   (6) public int close( ) :我们在使用完后,必须对我们打开的流进行关闭.

 

OutputSteam:输出字节流。继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位 byte[])。

  1. OutputStream 是所有的输出字节流的父类,它是一个抽象类。

  2. ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,

  3. ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。

 

OutputSteam类中的常用方法: 

 

     (1) public void write(byte b[ ]):将参数b中的字节写到输出流。 

     (2) public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。 

     (3) public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。 

     (4) public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。 

     (5) public void close( ) : 关闭输出流并释放与流相关的系统资源。

 

Reader:输入字符流。继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位 char[])。

  1. Reader 是所有的输入字符流的父类,它是一个抽象类。

  2. CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。

  3. BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。

  4. FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。

  5. InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。

Reader类中的常用方法:

     (1)  public int read() throws IOException; //读取一个字符,返回值为读取的字符

     (2)  public int read(char cbuf[]) throws IOException; /*读取一系列字符到数组cbuf[]中,返回值为实际读取的字符的数量*/

     (3)  public abstract int read(char cbuf[],int off,int len) throws IOException; /*读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量,该方法必须由子类实现*/

 

Writer:输出字符流。继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位 char[])。

  1. Writer 是所有的输出字符流的父类,它是一个抽象类。

  2. CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,

  3. BufferedWriter 是一个装饰器为Writer 提供缓冲功能。

  4. PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。

  5. OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类。

Writer类中的常用方法

     (1)  public void write(int c) throws IOException; //将整型值c的低16位写入输出流 

     (2)  public void write(char cbuf[]) throws IOException; //将字符数组cbuf[]写入输出流 

     (3)  public abstract void write(char cbuf[],int off,int len) throws IOException; //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流 

               (4)  public void write(String str) throws IOException; //将字符串str中的字符写入输出流 

     (5)  public void write(String str,int off,int len) throws IOException; //将字符串str 中从索引off开始处的len个字符写入输出流 

     (6)  flush( ) //刷空输出流,并输出所有被缓存的字节。 

     (7) close()   关闭流 public abstract void close() throws IOException

 

 

Java输入输出流有两个对称性

  1. 输入-输出对称: InputStream和OutputStream各自在Byte流输入和输出的两个平行结构的等级的根部;Reader和Writer各自在Char流输入和输出的两个平行结构的根部

  2. byte-char对称:InputStream和Reader的子类分别负责Byte和Char流的输入;OutputStream和Writer的子类分别负责Byte和Char流的输出。分别形成平行的等级结构。

 

3.常用的IO流

1.字节流中原始流的代表:FileInputStream FileOutputStream

FileInputStream 从一个文件中读取byte[]

FileOutputStream 将byte[]写入到一个文件中

FileInputStream/FileOutputStream的例子

具体的内容是:从利用FileInputStream从input.txt中读出byte流,用某种编码格式转换为String显示出来,然后将String转换成byte流,利用FileOutputStream将byte流写入到output.txt中

技术分享
 1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileNotFoundException; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.nio.ByteBuffer; 7 import java.nio.charset.Charset; 8  9 public class FileStreamDemo {10     public static void main(String[] args) {11         try {12             FileInputStream fis = new FileInputStream(new File("input.txt"));13             byte[] bis = new byte[fis.available()];14             fis.read(bis);15             fis.close();16             /*17              * 关于byte[]转换为String编码配置有两种方法,建议使用第二种方案 1.String str = new18              * String(b,"charsetname") 2.Charset charset = =19              * Charset.forName("charsetname"); String str =20              * charset.decode(ByteBuffer.wrap(b)).toString();21              */22             Charset charset = Charset.forName("UTF-8");23             String str = charset.decode(ByteBuffer.wrap(bis)).toString();24             // String str = new String(bis);25             // //byte转换为String,默认的编码是"ISO-8859-1",即根据编辑器的编码来确定编码方式26             System.out.println(str);27 28             FileOutputStream fos = new FileOutputStream(new File("output.txt"));29             byte[] bos = str.getBytes();30             fos.write(bos);31             fos.close();32 33         } catch (FileNotFoundException e) {34             // TODO Auto-generated catch block35             e.printStackTrace();36         } catch (IOException e) {37             // TODO Auto-generated catch block38             e.printStackTrace();39         }40 41     }42 }
FileStreamDemo.java

 

 2.字节流中装饰流之BufferInputStream BufferOutputStream

BufferInputStream:将原始InputStream中的byte[]读到内存缓存区中,然后从缓冲区读取byte[]

BufferOutputStream:向一个缓冲区中写入byte[],将缓冲区中的byte[]写入到原始outputStream中

BufferInputStream和BufferoutputStream对原始输入输出流进行装饰,使得流的读/写操作使用缓冲机制,这样不会对每次的流读/写操作都产生一个物理的读/写操作,从而提高了程序的效率。涉及物理流的地方,如控制台I/O,文件I/O等,都应当使用这个装饰流处理器。

举例:

技术分享
 1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.nio.ByteBuffer; 9 import java.nio.charset.Charset;10 11 public class BufferStreamDemo {12     public static void main(String[] args) {13         try {14 15             FileInputStream fis = new FileInputStream(new File("input.txt"));16             BufferedInputStream bfis = new BufferedInputStream(fis);17             byte[] bis = new byte[bfis.available()];18             bfis.read(bis);19             bfis.close();20             fis.close();21             /*22              * 关于byte[]转换为String编码配置有两种方法,建议使用第二种方案 1.String str = new23              * String(b,"charsetname") 2.Charset charset = =24              * Charset.forName("charsetname"); String str =25              * charset.decode(ByteBuffer.wrap(b)).toString();26              */27             Charset charset = Charset.forName("UTF-8");28             String str = charset.decode(ByteBuffer.wrap(bis)).toString();29             // String str = new String(bis);30             // //byte转换为String,默认的编码是"ISO-8859-1",即根据编辑器的编码来确定编码方式31             System.out.println(str);32 33             FileOutputStream fos = new FileOutputStream(new File("output.txt"));34             BufferedOutputStream bfos = new BufferedOutputStream(fos);35             byte[] bos = str.getBytes();36             bfos.write(bos);37             bfos.close();38             fos.close();39         } catch (FileNotFoundException e) {40             // TODO Auto-generated catch block41             e.printStackTrace();42         } catch (IOException e) {43             // TODO Auto-generated catch block44             e.printStackTrace();45         }46 47     }48 }
BufferStreamDemo.java

 

3.字节装饰流之ObjectInputStream ObjectOutputStream

ObjectInputStream :对象输入流,将使用ObjectOutputStream串行化的原始数据类型和对象重新并行化

ObjectOutputStream:对象输出流,将原始数据类型和对象串行化

使用ObjectInputStream/ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入

举例:

技术分享
 1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.nio.ByteBuffer; 9 import java.nio.charset.Charset;10 11 public class BufferStreamDemo {12     public static void main(String[] args) {13         try {14 15             FileInputStream fis = new FileInputStream(new File("input.txt"));16             BufferedInputStream bfis = new BufferedInputStream(fis);17             byte[] bis = new byte[bfis.available()];18             bfis.read(bis);19             bfis.close();20             fis.close();21             /*22              * 关于byte[]转换为String编码配置有两种方法,建议使用第二种方案 1.String str = new23              * String(b,"charsetname") 2.Charset charset = =24              * Charset.forName("charsetname"); String str =25              * charset.decode(ByteBuffer.wrap(b)).toString();26              */27             Charset charset = Charset.forName("UTF-8");28             String str = charset.decode(ByteBuffer.wrap(bis)).toString();29             // String str = new String(bis);30             // //byte转换为String,默认的编码是"ISO-8859-1",即根据编辑器的编码来确定编码方式31             System.out.println(str);32 33             FileOutputStream fos = new FileOutputStream(new File("output.txt"));34             BufferedOutputStream bfos = new BufferedOutputStream(fos);35             byte[] bos = str.getBytes();36             bfos.write(bos);37             bfos.close();38             fos.close();39         } catch (FileNotFoundException e) {40             // TODO Auto-generated catch block41             e.printStackTrace();42         } catch (IOException e) {43             // TODO Auto-generated catch block44             e.printStackTrace();45         }46 47     }48 }
BufferStreamDemo.java
技术分享
 1 import java.io.*; 2  3 public class Student implements Serializable { 4  5     String name; 6     int id; 7     int age; 8     String department; 9 10     public Student(String name, int id, int age, String department) {11         this.age = age;12         this.department = department;13         this.id = id;14         this.name = name;15     }16 }
Student.java

 

4.字节装饰流之DataInputStream DataOutputStream

DataInputStream:提供基于多字节的读取方法,可以读取原始数据类型的数据

DataOutputStream:提供基于多字节的写出方法,可以写出原始数据类型的数据

举例:

技术分享
 1 public class Member { 2     private String name; 3     private int age; 4  5     public Member() { 6     } 7  8     public Member(String name, int age) { 9         this.name = name;10         this.age = age;11     }12 13     public void setName(String name) {14         this.name = name;15     }16 17     public void setAge(int age) {18         this.age = age;19     }20 21     public String getName() {22         return name;23     }24 25     public int getAge() {26         return age;27     }28 }
Member.java
技术分享
 1 import java.io.*; 2  3 public class DataStreamDemo { 4     public static void main(String[] args) { 5         Member[] members = { new Member("Justin", 90), new Member("momor", 95), 6                 new Member("Bush", 88) }; 7         try { 8             DataOutputStream dataOutputStream = new DataOutputStream( 9                     new FileOutputStream(new File("file.txt")));10 11             for (Member member : members) {12                 // 写入UTF字符串13                 dataOutputStream.writeUTF(member.getName());14                 // 写入int数据15                 dataOutputStream.writeInt(member.getAge());16             }17 18             // 所有数据至目的地19             dataOutputStream.flush();20             // 关闭流21             dataOutputStream.close();22 23             DataInputStream dataInputStream = new DataInputStream(24                     new FileInputStream(new File("file.txt")));25 26             // 读出数据并还原为对象27             for (int i = 0; i < members.length; i++) {28                 // 读出UTF字符串29                 String name = dataInputStream.readUTF();30                 // 读出int数据31                 int score = dataInputStream.readInt();32                 members[i] = new Member(name, score);33             }34 35             // 关闭流36             dataInputStream.close();37 38             // 显示还原后的数据39             for (Member member : members) {40                 System.out41                         .printf("%s\t%d%n", member.getName(), member.getAge());42             }43         } catch (IOException e) {44             e.printStackTrace();45         }46     }47 }
DataStreamDemo.java

 

5.字符流 之StringReader和StringWriter

StringReader:数据从String中读取到char[]

StringWriter:将char[]写入到String中

举例:

技术分享
 1 import java.io.IOException; 2 import java.io.StringReader; 3 import java.io.StringWriter; 4  5 public class StringStreamTest { 6     public static void main(String[] args) { 7         String str = "abcdefghijklmn"; 8         transform(str); 9     }10 11     public static void transform(String str) {12         StringReader sr = new StringReader(str);13         StringWriter sw = new StringWriter();14         char[] chars = new char[1024];15         try {16             int len = 0;17             while ((len = sr.read(chars)) != -1) {18                 String strRead = new String(chars, 0, len).toUpperCase();19                 System.out.println(strRead);20                 sw.write(strRead);21                 sw.flush();22             }23             sr.close();24             sw.close();25         } catch (IOException e) {26             e.printStackTrace();27         } finally {28             sr.close();29             try {30                 sw.close();31             } catch (IOException e) {32                 e.printStackTrace();33             }34         }35     }36 }
StringStreamTest.java

 

6.字符装饰流之 BufferedReader/BufferedWriter

BufferedReader/BufferedWriter的作用和BufferInputStream/BufferOutputStream类似,但BufferedReader提供了一个readline方法,可以将存储的一行的char[]读取出来

举例:

技术分享
 1 import java.io.*; 2  3 class BufferReaderDemo { 4     public static void main(String arg[]) throws IOException { 5         BufferedReader b = new BufferedReader(new FileReader("c.txt")); 6         boolean c; 7         do { 8             String s = b.readLine(); 9             System.out.println(s);10         } while (c = b.read() != -1);11     }12 }
BufferReaderDemo.java

 

7.从byte流到char流的适配 InputStreamReader和OutputStreamWriter

byte流到char流的适配是通过InputStreamReader和OutputStreamWriter来解决的

InputStreamReader:是字节流通向字符流的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如 GBK 等

要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

 

OutputStreamWriter :是字符流通向字节流的桥梁。
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积

为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));

举例:

技术分享
 1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStreamReader; 7 import java.io.OutputStreamWriter; 8  9 public class StreamReaderWriterDemo {10     public static void main(String[] args) {11         try {12 13             BufferedReader bufr = new BufferedReader(new InputStreamReader(14                     new FileInputStream("f:\\01.txt")));15 16             BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(17                     new FileOutputStream("f:\\02.txt")));18 19             int ch = 0;20 21             // 以字符方式显示文件内容22             while ((ch = bufr.read()) != -1) {23                 System.out.print((char) ch);24                 bufw.write(ch);25             }26             if (bufr != null)27                 bufr.close();28             if (bufw != null)29                 bufw.close();30         } catch (ArrayIndexOutOfBoundsException e) {31             e.printStackTrace();32         } catch (IOException e) {33             e.printStackTrace();34         }35     }36 }
StreamReaderWriterDemo.java

 

8. InputStreamReader和OutputStreamWriter的子类:FileReader 和FileWriter

FileReader:文件字节流通向字符流的桥梁

FileWriter:是字符流通向文件字节流的桥梁。

举例:

技术分享
 1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6  7 public class TestWriter { 8     // 功能:读取E:/Test.txt文件的内容(一行一行读),并将其内容写入E:/Jack.txt中 9     // 知识点:java读文件、写文件---<以字符流方式>10     public static void main(String[] args) {11         try {12             // 创建FileReader对象,用来读取字符流13             FileReader fr = new FileReader("E:/Test.txt");14             // 缓冲指定文件的输入15             BufferedReader br = new BufferedReader(fr);16             // 创建FileWriter对象,用来写入字符流17             FileWriter fw = new FileWriter("E:/Jack.txt");18             // 将缓冲对文件的输出19             BufferedWriter bw = new BufferedWriter(fw);20             // 定义一个String类型的变量,用来每次读取一行21             String myreadline;22             while (br.ready()) {23                 // 读取一行24                 myreadline = br.readLine();25                 // 写入文件26                 bw.write(myreadline);27                 bw.newLine();28                 // 在屏幕上输出29                 System.out.println(myreadline);30             }31             // 刷新该流的缓冲32             bw.flush();33             bw.close();34             br.close();35             fw.close();36             br.close();37             fr.close();38 39         } catch (IOException e) {40             e.printStackTrace();41         }42     }43 }
TestWriter.java

 

 

参考文章:

Java输入输出流详解 http://blog.csdn.net/zsw12013/article/details/6534619

Java IO流分析整理  http://www.th7.cn/Program/java/201406/214540.shtml

Java输入输出流      http://blog.csdn.net/hguisu/article/details/7418161

《Java与模式》第27章 专题:设计模式在Java I/O库中的应用

 ObjectInputStream与ObjectOutputStream类 http://blog.sina.com.cn/s/blog_77cb34170100r5o6.html

 使用StringReader和StringWriter操作字符串 http://blog.csdn.net/zhuhezan/article/details/6526915

InputStreamReader和OutputStreamWriter的用法 http://blog.csdn.net/z69183787/article/details/8179889

Java FileReader FileWriter 示例  http://blog.163.com/jackswu@yeah/blog/static/1406291232011076011170/

Java IO流