java io 层次结构图 io详解

Java中IO结构总图

在这里插入图片描述

Java 流在处理上分为字符流和字节流。字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。
Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换。而类 InputStreamReader 和 OutputStreamWriter 处理字符流和字节流的转换。字符流(一次可以处理一个缓冲区)一次操作比字节流(一次一个字节)效率高。

( 一 )以字节为导向的 stream------InputStream/OutputStream

InputStream 和 OutputStream 是两个 abstact 类,对于字节为导向的 stream 都扩展这两个鸡肋(基类 _ ) ;

1、InputStream
这里写图片描述

1.1 ByteArrayInputStream – 把内存中的一个缓冲区作为 InputStream 使用 .
构造方法:
(A)ByteArrayInputStream(byte[]) 创建一个新字节数组输入流( ByteArrayInputStream ),它从指定字节数组中读取数据( 使用 byte 作为其缓冲区数组)
(B)—ByteArrayInputStream(byte[], int, int) 创建一个新字节数组输入流,它从指定字节数组中读取数据。 —mark:: 该字节数组未被复制。

1.2 StringBufferInputStream – 把一个 String 对象作为 InputStream .
构造方法:
StringBufferInputStream(String) 据指定串创建一个读取数据的输入流串。 注释:不推荐使用 StringBufferInputStream 方法。 此类不能将字符正确的转换为字节。 同 JDK 1.1 版中的类似,从一个串创建一个流的最佳方法是采用 StringReader 类。

1.3 FileInputStream – 把一个文件作为 InputStream ,实现对文件的读取操作
构造方法:
(A)FileInputStream(File name) 创建一个输入文件流,从指定的 File 对象读取数据。
(B)FileInputStream(FileDescriptor) 创建一个输入文件流,从指定的文件描述器读取数据。
©-FileInputStream(String name) 创建一个输入文件流,从指定名称的文件读取数据。
read() 从当前输入流中读取一字节数据。 read(byte[]) 将当前输入流中 b.length 个字节数据读到一个字节数组中。
read(byte[], int, int) 将输入流中 len 个字节数据读入一个字节数组中。

1.4 PipedInputStream :实现了 pipe 的概念,主要在线程中使用 . 管道输入流是指一个通讯管道的接收端。 一个线程通过管道输出流发送数据,而另一个线程通过管道输入流读取数据,这样可实现两个线程间的通讯。
构造方法:
PipedInputStream() 创建一个管道输入流,它还未与一个管道输出流连接。 PipedInputStream(PipedOutputStream) 创建一个管道输入流 , 它已连接到一个管道输出流。

1.5 SequenceInputStream :把多个 InputStream 合并为一个 InputStream . “序列输入流”类允许应用程序把几个输入流连续地合并起来, 并且使它们像单个输入流一样出现。每个输入流依次被读取,直到到达该流的末尾。 然后“序列输入流”类关闭这个流并自动地切换到下一个输入流。
构造方法:
SequenceInputStream(Enumeration) 创建一个新的序列输入流,并用指定的输入流的枚举值初始化它。
SequenceInputStream(InputStream, InputStream) 创建一个新的序列输入流,初始化为首先 读输入流 s1, 然后读输入流 s2 。

public class TestSequence {  
  public static void main(String[] args)throws Exception{  
  //不管怎么样,先创建两个文件。从里面读取数据,(我的文件里面有内容!)  
  InputStream in1=new FileInputStream(new File("d:\\jack.txt"));  
  InputStream in2=new FileInputStream(new File("d:\\jack2.txt"));  
  //读取,数据后要生成的文件  
  OutputStream ou=new FileOutputStream(new File("d:\\jack3.txt"));  
  //创建SequenceInputStream类,  
  SequenceInputStream si=new SequenceInputStream(in1,in2);  
  //因为SequenceInputStream,是一个字节一个字节读,要判断一下是否读完了。  
  int c=0;  
  while((c=si.read())!=-1){  
  //这里也是一个字节一个字节写的。  
  ou.write(c);  
  }  
  //关闭所有的资源  
  si.close();  
  ou.close();  
  in2.close();  
  in1.close();  
  }  
  } 

1.6 ObjectInputStream:用于操作Object的stream,这个在stream主要用在对象传输的过程中,其中牵涉到了序列化的知识
构造方法:
ObjectInputStream():实例化一个ObjectInputStream对象
ObjectInputStream(InputStream):使用一个InputStream对象来实例化一个ObjectInputStream对象,其中InputStream就是对象的输入流
方法:
实现了InputStream中的部分方法;
它自己有很多的额外的方法:
这里就只介绍一下readObject(Object)方法,就是将一个对象写入到stream中,但是这个object必须序列化
其他的还有像readInt,readFloat等这样基本类型的方法,因为基本类型对应的对象也都是Object.

1.7 FilterInputStream:是一个过滤的InputStream
构造方法:
FilterInputStream(InputStream):使用一个InputStream为参数实例化一个FilterInputStream,其实就是来修饰InputStream的
方法:
实现了InputStream中的所有方法
他其实没有作用,他的众多子类是很有用的:
1.7.1 BufferedInputStream:使用缓冲区的stream
构造方法:
BufferedInputStream(InputStream):使用InputStream为参数初始化实例
BufferedInputStream(InputStream,int):能够设置缓冲区大小的BufferedInputStream
方法:
实现了FilterInputStream中的所有方法(其实也是实现了InputStream中的所有方法)

        /**
         * 字节缓冲流
         * BufferedInputStream/BufferedOutputStream
         * 基本原理:缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
         */
    public static void main(String[] args) throws Exception{
        FileInputStream file1 = new FileInputStream("D:\\Desktop\\file1.txt");
        //1.创建字节缓冲输入流
        BufferedInputStream buf1 = new BufferedInputStream(file1);

        //2.读取
		//int read = buf1.read();
		//System.out.println(read);       //49
		//System.out.println((char) read);//1

        //3.创建缓冲区
        byte[] bytes = new byte[1024];
        int count = 0;
        while ((count=buf1.read(bytes)) != -1){
            System.out.println(new String(bytes, 0, count));
        }
        //4.关闭流(内部调用了flush方法),buf1关闭,file1也关闭了
        buf1.close();

1.7.2 DataInputStream:数字格式化的stream

构造方法:
DataInputStream(InputStream):使用InputStream参数来初始化实例
方法:
实现了FilterInputStream中的部分方法
额外的方法:
readInt,readFloat,readDouble…这样可以直接从stream中读取基本类型的数据
还有其他的类就不做解释了,因为用到的很少了,有的可能一辈子都用不到。

OutputSteam

这里写图片描述

2.1 ByteArrayOutputStream : 把信息存入内存中的一个缓冲区中 . 该类实现一个以字节数组形式写入数据的输出流。
当数据写入缓冲区时,它自动扩大。用 toByteArray() 和 toString() 能检索数据。
构造方法:
(A)— ByteArrayOutputStream() 创建一个新的字节数组输出流。
(B)— ByteArrayOutputStream() 创建一个新的字节数组输出流。
©— ByteArrayOutputStream(int) 创建一个新的字节数组输出流,并带有指定大小字节的缓冲区容量。
方法:
toString(String) 根据指定字符编码将缓冲区内容转换为字符串,并将字节转换为字符。
write(byte[], int, int) 将指定字节数组中从偏移量 off 开始的 len 个字节写入该字节数组输出流。
write(int) 将指定字节写入该字节数组输出流。
writeTo(OutputStream) 用 out.write(buf, 0, count) 调用输出流的写方法将该字节数组输出流的全部内容写入指定的输出流参数。
2.2 FileOutputStream: 文件输出流是向 File 或 FileDescriptor 输出数据的一个输出流。
构造方法:
(A)FileOutputStream(File name) 创建一个文件输出流,向指定的 File 对象输出数据。
(B)FileOutputStream(FileDescriptor) 创建一个文件输出流,向指定的文件描述器输出数据。
©FileOutputStream(String name) 创建一个文件输出流,向指定名称的文件输出数据。
(D)FileOutputStream(String, boolean) 用指定系统的文件名,创建一个输出文件。
2.3 PipedOutputStream: 管道输出流是指一个通讯管道的发送端。 一个线程通过管道输出流发送数据,
而另一个线程通过管道输入流读取数据,这样可实现两个线程间的通讯。
构造方法:
(A)PipedOutputStream() 创建一个管道输出流,它还未与一个管道输入流连接。
(B)PipedOutputStream(PipedInputStream) 创建一个管道输出流,它已连接到一个管道输入流。

下面来看一下PipedInputStream和PipedOutputStream的例子:

package com.io.demo;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class IO {

    public static void main(String[] args) throws Exception{

        PipedOutputStream pos = new PipedOutputStream();
        try {
            PipedInputStream pis = new PipedInputStream(pos);
            new Thread(new InputStreamRunnable(pis)).start();
            new Thread(new OutputStreamRunnable(pos)).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class InputStreamRunnable implements Runnable{
        private PipedInputStream pis = null;
        public InputStreamRunnable(PipedInputStream pis){
            this.pis = pis;
        }
        @Override
        public void run() {
            BufferedReader sr = new BufferedReader(new InputStreamReader(pis));
            try {
                System.out.println("读取到的内容:"+sr.readLine());
                sr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    static class OutputStreamRunnable implements Runnable{
        private PipedOutputStream pos = null;
        public OutputStreamRunnable(PipedOutputStream pos){
            this.pos = pos;
        }
        @Override
        public void run(){
            try {
                pos.write("Hello World!".getBytes());
                pos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

其实PipedInputStream/PipedOutputStream相当于消费者和生产者机制。

2.4 ObjectOutputStream: 输出Object对象的stream
构造方法:
ObjectOutputStream:实例化一个ObjectOutputStream对象
ObjectOutputStream(OutputStream):使用OutputStream对象来实例化一个ObjectOutputStream对象,将对象写入到OutputStream中

方法:
实现了OutputStream中的部分方法
额外的方法:
这里只介绍一个writeObject(Object):将一个对象Object写入到OutputStream中
同时他也有writeInt,writeFloat…这样的基本类型的方法,因为基本类型对应的对象类型都是Object的子类
关于ObjectInputStream/ObjectOutputStream主要用与将一个对象Object写入到本地或者是在网络中进行传输的,所以这些对象需要进行序列化操作。

2.5 FilterOutputStream:过滤OutputStream

constructor—
FilterOutputStream(OutputStream):使用OutputStream参数实例化FilterOutputStream

method—

实现了OutputStream的所有方法
和FilterInputStream一样,他其实也没有什么用途,他的子类很有用的

2.5.1 BufferedOutputStream:带有缓冲区的stream

构造方法:
BufferedOutputStream(OutputStream):使用OutputStream参数初始化BufferedOutputStream类
BufferedOutputStream(OutputStream,int):在初始化实例的时候指定缓冲区的大小
方法:
实现了FilterOutputStream中的部分方法
2.5.2 DataOutputStream:具有格式化的OutputStream

构造方法:
DataOutputStream(OutputStream):使用OutputStream参数来初始化DataOutputStream实例

方法:
实现了FilterOutputStream中的部分方法
writeInt,writeFloat,writeDouble….能够给直接向stream中写入基本类型的方法

2.5.3 PrintStream:直接输出到控制台中:我们最熟悉的就是System.out他就是一个PrintStream

构造方法:
PrintStream(OutputStream):使用OutputStream参数来实例化PrintStream
方法:
实现了FilterOutputStream中的部分方法
print()有多个重载的方法,8中基本类型和String类型,同时他还可以进行格式化输出。

( 二 )以字符为导向的 stream Reader/Writer

以 Unicode 字符为导向的 stream ,表示以 Unicode 字符为单位从 stream 中读取或往 stream 中写入信息。
Reader/Writer 为 abstact 类
以 Unicode 字符为导向的 stream 包括下面几种类型:

1. Reader

这里写图片描述

1.1 CharArrayReader :与 ByteArrayInputStream 对应此类实现一个可用作字符输入流的字符缓冲区
CharArrayReader(char[]) 用指定字符数组创建一个 CharArrayReader 。
CharArrayReader(char[], int, int) 用指定字符数组创建一个 CharArrayReader
1.2 StringReader : 与 StringBufferInputStream 对应其源为一个字符串的字符流。
StringReader(String) 创建一新的串读取者。
1.3 FileReader : 与 FileInputStream 对应
1.4 PipedReader : 与 PipedInputStream 对应
1.5 InputStreamReader:将InputStream转化成Reader

2、Writer

这里写图片描述

2.1 CharArrayWrite : 与 ByteArrayOutputStream 对应
2.2 StringWrite :无与之对应的以字节为导向的 stream
2.3 FileWrite : 与 FileOutputStream 对应
2.4 PipedWrite :与 PipedOutputStream 对应
2.5 OutputStreamWriter:将OutputStream转化成Writer

3、两种不同导向的 stream 之间的转换

3.1 InputStreamReader 和 OutputStreamWriter :
把一个以字节为导向的 stream 转换成一个以字符为导向的 stream 。
InputStreamReader 类是从字节流到字符流的桥梁:它读入字节,并根据指定的编码方式,将之转换为字符流。
使用的编码方式可能由名称指定,或平台可接受的缺省编码方式。
InputStreamReader 的 read() 方法之一的每次调用,可能促使从基本字节输入流中读取一个或多个字节。
为了达到更高效率,考虑用 BufferedReader 封装 InputStreamReader ,
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

例如: // 实现从键盘输入一个整数

String s = null;             
InputStreamReader re = new InputStreamReader(System.in);  
BufferedReader br = new BufferedReader(re);  
      try {  
         s = br.readLine();  
         System.out.println("s= " + Integer.parseInt(s));  
         br.close();  
      }catch (IOException e){  
           e.printStackTrace();  
      }catch(NumberFormatException e)// 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。  
          {  
             System.out.println(" 输入的不是数字 ");  
          }  

InputStreamReader(InputStream) 用缺省的字符编码方式,创建一个 InputStreamReader 。
InputStreamReader(InputStream, String) 用已命名的字符编码方式,创建一个 InputStreamReader 。

OutputStreamWriter 将多个字符写入到一个输出流,根据指定的字符编码将多个字符转换为字节。
每个 OutputStreamWriter 合并它自己的 CharToByteConverter, 因而是从字符流到字节流的桥梁。

(三)Java IO 的一般使用原则 :

一、按数据来源(去向)分类:
1 、是文件: FileInputStream, FileOutputStream, ( 字节流 )FileReader, FileWriter( 字符 )
2 、是 byte[] : ByteArrayInputStream, ByteArrayOutputStream( 字节流 )
3 、是 Char[]: CharArrayReader, CharArrayWriter( 字符流 )
4 、是 String: StringBufferInputStream, StringBufferOuputStream ( 字节流 )StringReader, StringWriter( 字符流 )
5 、网络数据流: InputStream, OutputStream,( 字节流 ) Reader, Writer( 字符流 )
二、按是否格式化输出分:
1 、要格式化输出: PrintStream, PrintWriter
三、按是否要缓冲分:
1 、要缓冲: BufferedInputStream, BufferedOutputStream,( 字节流 ) BufferedReader, BufferedWriter( 字符流 )
四、按数据格式分:
1 、二进制格式(只要不能确定是纯文本的) : InputStream, OutputStream 及其所有带 Stream 结束的子类
2 、纯文本格式(含纯英文与汉字或其他编码方式); Reader, Writer 及其所有带 Reader, Writer 的子类
五、按输入输出分:
1 、输入: Reader, InputStream 类型的子类
2 、输出: Writer, OutputStream 类型的子类
六、特殊需要:
1 、从 Stream 到 Reader,Writer 的转换类: InputStreamReader, OutputStreamWriter
2 、对象输入输出: ObjectInputStream, ObjectOutputStream
3 、进程间通信: PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
4 、合并输入: SequenceInputStream
5 、更特殊的需要: PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader
决定使用哪个类以及它的构造进程的一般准则如下(不考虑特殊需要):
首先,考虑最原始的数据格式是什么: 原则四
第二,是输入还是输出:原则五
第三,是否需要转换流:原则六第 1 点
第四,数据来源(去向)是什么:原则一
第五,是否要缓冲:原则三 (特别注明:一定要注意的是 readLine() 是否有定义,有什么比 read, write 更特殊的输入或输出方法)
第六,是否要格式化输出:原则二

  • 14
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值