Java IO流

1.流的概念

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

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

输出流:

输入流:

2.Java输入输出流

image

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 = new
18              * 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 block
35             e.printStackTrace();
36         } catch (IOException e) {
37             // TODO Auto-generated catch block
38             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 = new
23              * 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 block
41             e.printStackTrace();
42         } catch (IOException e) {
43             // TODO Auto-generated catch block
44             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 = new
23              * 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 block
41             e.printStackTrace();
42         } catch (IOException e) {
43             // TODO Auto-generated catch block
44             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.out
41                         .printf("%s	%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

 9.PrintStream  OutputStream

PrintStream在OutputStream基础之上提供了增强的功能,即可以方便地输出各种类型的数据(而不仅限于byte型)的格式化表示形式。PrintStream的方法从不抛出IOException。

System.out是PrintStream的实例(注意System.in是一个BufferInputStream)

下面是一个Socket实例,使用了PrintStream System.out System.in

 1 package zyb.org.client;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.IOException;
 5 import java.io.InputStreamReader;
 6 import java.io.PrintStream;
 7 import java.net.Socket;
 8 import java.net.SocketTimeoutException;
 9 
10 public class Client1 {
11     public static void main(String[] args) throws IOException {
12         //客户端请求与本机在20006端口建立TCP连接 
13         Socket client = new Socket("127.0.0.1", 20006);
14         client.setSoTimeout(10000);
15         //获取键盘输入 
16         BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
17         //获取Socket的输出流,用来发送数据到服务端  
18         PrintStream out = new PrintStream(client.getOutputStream());
19         //获取Socket的输入流,用来接收从服务端发送过来的数据  
20         BufferedReader buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
21         boolean flag = true;
22         while(flag){
23             System.out.print("输入信息:");
24             String str = input.readLine();
25             //发送数据到服务端  
26             out.println(str);
27             if("bye".equals(str)){
28                 flag = false;
29             }else{
30                 try{
31                     //从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常
32                     String echo = buf.readLine();
33                     System.out.println(echo);
34                 }catch(SocketTimeoutException e){
35                     System.out.println("Time out, No response");
36                 }
37             }
38         }
39         input.close();
40         if(client != null){
41             //如果构造函数建立起了连接,则关闭套接字,如果没有建立起连接,自然不用关闭
42             client.close();    //只关闭socket,其关联的输入输出流也会被关闭
43         }
44     }
45 }
Socket示例

参考文章:

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/

 printStream 和printWriter区别  http://blog.csdn.net/y3wegy/article/details/8783314

 【Java TCP/IP Socket】TCP Socket(含代码) http://blog.csdn.net/ns_code/article/details/14105457

原文地址:https://www.cnblogs.com/xerrard/p/4244114.html