Java IO流

1.流的概念

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

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

输出流:

Java IO流

输入流:

Java IO流

 

2.Java输入输出流

image

 

Java IO流

Java IO流

Java IO流

Java IO流

 

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\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

 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

你可能感兴趣的:(java io)