java中的IO基础总结

java中的I/O类库设计可谓是比较丰富的,在我们平时的编程中也经常接触到,往往大部分的系统都有对IO操作的一些封装代码,平时要用到往往翻翻api或者找个写好的方法复制就搞定,由此带来的是对java本身提供的这些方法不熟悉,平时不好好梳理下,对java的io包下面这些常用类也就比较凌乱了。所以这里通过api文档和java.io下面的源码去整理下。

1、表示字节输入输出流的所有类的超类(InputStream/OutputStream)

构造方法:
InputStream() 创建一个输入的stream流

方法:
int   available():返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
void   close():关闭此输入流并释放与该流关联的所有系统资源。
abstract int   read():从输入流中读取数据的下一个字节。
int   read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int   read(byte[] b, int off, int len):将输入流中最多 len 个数据字节读入 byte 数组。
long   skip(long n):跳过和丢弃此输入流中数据的 n 个字节。
boolean   mark(int readlimit):在此输入流中标记当前的位置。
boolean   markSupported():测试此输入流是否支持 mark 和 reset 方法。
void   reset():将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。

从上面看到,read()方法是abstract修饰的,是依靠子类去实现的,当到达流的末尾时,返回-1。
markSupported,mark,reset一般配合使用。
InputStream的available()方法返回0,close()方法是空实现,默认markSupported()方法返回false。

1.1 ByteArrayInputStream 包含一个内部缓冲区的输入流。
ByteArrayInputStream继承了InputStream,提供了两个以字节为输入的构造函数。
ByteArrayInputStream实现了自己的read方法,同时重写了markSupported()方法返回true,表示支持标记,也就支持mark()和reset()方法。
另一方面,ByteArrayInputStream的close()方法是空实现的,是没有作用的,关闭流后任然可以被调用,不会抛出IOException。

1.2 FileInputStream 从文件系统中的某个文件中获得输入字节。
FileInputStream实现了InputStream的部分方法,提供三个构造方法来构造文件输入流。
并且增加了两个额外的方法:
FileChannel getChannel():返回与此文件输入流有关的唯一 FileChannel 对象,使用java的NIO就会经常用到这个方法。
FileDescriptor getFD():返回表示到文件系统中实际文件的连接的 FileDescriptor 对象,该文件系统正被此 FileInputStream 使用。

1.3 PipeInputStream 管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。
增加了两个方法:
void connect(PipedOutputStream src):使此管道输入流连接到管道输出流 src。
protected  void    receive(int b):接收数据字节。

1.4 StringBufferInputStream     已过时。 此类未能正确地将字符转换为字节。

1.5 SequenceInputStream 表示其他输入流的逻辑串联。
SequeneceInputStream从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

1.6 ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
ObjectInputStream在继承了InputStream的基础上,实现了ObjectInput接口,而ObjectInput接口继承了DataInput接口,提供了对java对象和基本数据类型的读取操作。
ObjectInputStream(InputStream in):创建从指定 InputStream 读取的 ObjectInputStream。
注意:只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

1.7 FilterInputStream 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。
java中的IO再设计上使用了装饰器模式,FilterInputStream便是装饰角色,而它的子类则是具体装饰角色,FilterInputStream 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

1.7.1 DataInputStream 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。
DataInputStream是FilterInputStream 的子类,同样,它也实现了DataInput接口,提供了对对象和基本类型的读取操作。
DataInputStream对于多线程访问不一定是安全的。

1.7.2 BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。
BufferedInputStream继承了FilterInputStream,在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。

1.7.3 PushbackInputStream 为另一个输入流添加性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。
在实现FilterInputStream部分方法的同时,提供了三个额外的方法,实现“推回”或“取消读取”
void unread(byte[] b):推回一个 byte 数组:将其复制到推回缓冲区之前。
void unread(byte[] b, int off, int len):推回 byte 数组的某一部分:将其复制到推回缓冲区之前。
void unread(int b):推回一个字节:将其复制到推回缓冲区之前。

 2. 用于读取和写入字符流的抽象类(Reader/Writer)

构造方法:
protected    Reader():创建一个新的字符流 reader,其重要部分将同步其自身的 reader。
protected    Reader(Object lock):创建一个新的字符流 reader,其重要部分将同步给定的对象。

方法:
abstract    void close():关闭该流并释放与之关联的所有资源。
int    read():读取单个字符。
int    read(char[] cbuf):将字符读入数组。
abstract    int read(char[] cbuf, int off, int len):将字符读入数组的某一部分。
int    read(CharBuffer target):试图将字符读入指定的字符缓冲区。
boolean    ready():判断是否准备读取此流。
void     reset():重置该流。
void    mark(int readAheadLimit):标记流中的当前位置。
boolean    markSupported():判断此流是否支持 mark() 操作。
long    skip(long n):跳过字符。
可以看出,Reader和InputStream的提供的方法基本类似,Reader子类必须实现的方法只有 read(char[], int, int) 和 close(),ready()方法默认返回false,默认不支持markSupported,子类都可以重写。
Reader的已知子类基本和InputStream有一一对应的关系,这里就不列举说明了。

关于InputStream和Reader需要注意的几点:
1) 对于流的装饰,字节流使用FilterInputStream和FilterOutputStream来修改流以满足特殊需求,而字符流的类继承结构继续沿用相同思想,但并不完全相同。BufferedWriter并不是FilterWriter的子类。FilterWriter是抽象类但没有任何子类,把它放在那里只作为占位符。
2)DataInputStream也提供了readLine()方法,但是这个方法已经被废弃,读取文本行的首选方法是使用 BufferedReader.readLine() 方法。
使用 DataInputStream 类读取文本行的程序可以改为使用BufferedReader 类,只要将以下形式的代码:DataInputStream d = new DataInputStream(in);
替换为:BufferedReader d = new BufferedReader(new InputStreamReader(in));

3. 字节流通向字符流的桥梁(InputStreamReader)和字符流通向字节流的桥梁(OutputStreamWriter)
InputStreamReader 是字节流通向字符流的桥梁,它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
OutputStreamReader和InputStreamWriter类似,这里不加赘述。

public static void readFile(String fileName) throws IOException {
        InputStream inputStream = new FileInputStream(fileName);
        final int length = inputStream.available();//可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数
        System.out.println("流大小>>>>>" + length);
        System.out.println("FileInputStream是否支持markSupported()方法:" + inputStream.markSupported());

        System.out.println("========================================================");
        //将文件流装饰成BufferedInputStream,它为我们提供了mark和reset方法
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        System.out.println("bufferedInputStream是否支持markSupported()方法:" + bufferedInputStream.markSupported());
        bufferedInputStream.mark(0);//在第0处标记
        char firstChar = (char)bufferedInputStream.read();//读取下一个字节数据,如果到达流末尾,则返回 -1
        System.out.println("文件的第一个字节为:" + firstChar);
        char SecChar = (char)bufferedInputStream.read();//读取下一个字节数据,如果到达流末尾,则返回 -1
        System.out.println("文件的第二个字节为:" + SecChar);
        bufferedInputStream.reset();//回到标记位置
        char afterResetChar = (char)bufferedInputStream.read();
        System.out.println("reset方法后读取字节为:" + afterResetChar);
        bufferedInputStream.reset();

        System.out.println("========================================================");
        //再进行一次包装,用来读取字符//使用DataInputStream包装,提供java基本类型和对象的读取功能
        DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
        String firstUTF = dataInputStream.readUTF();//读取第一个中文字符
        System.out.println("文件第一个字符为:" + firstUTF);
        dataInputStream.reset();//由BufferedInputStream支持

        System.out.println("========================================================");
        InputStreamReader inputStreamReader = new InputStreamReader(dataInputStream, "UTF-8");        //进一步装饰成Reader,提供字符相关操作功能,提供readLine()
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String firstLine = bufferedReader.readLine();//读取第一行
        System.out.println("第一行内容为:" + firstLine);

        System.out.println("========================================================");
        LineNumberReader lineNumberReader = new LineNumberReader(bufferedReader);
        System.out.print("当前行号:" + lineNumberReader.getLineNumber());
    }

4.  一个自我独立的类(RandomAccessFile)支持对随机访问文件的读取和写入。
先看一下RandomAccessFile的方法定义:

public class RandomAccessFile implements DataOutput, DataInput, Closeable{}

可以看到,RandomAccessFile不使用InputStream和OutputStream中已有的任何功能,是一个独立的类。它适用于由大小已知的记录组成的文件,可以用seek()方法将记录一处转移到另一处,然后读取或修改记录,它实现了DataOutput和DataInput,可以提供读写功能。
先看一下DataInput接口的基本方法(DataOutput对应不赘述):

public interface DataInput {
    void readFully(byte[] var1) throws IOException;
    void readFully(byte[] var1, int var2, int var3) throws IOException;
    int skipBytes(int var1) throws IOException;
    boolean readBoolean() throws IOException;
    byte readByte() throws IOException;
    int readUnsignedByte() throws IOException;
    short readShort() throws IOException;
    int readUnsignedShort() throws IOException;
    char readChar() throws IOException;
    int readInt() throws IOException;
    long readLong() throws IOException;
    float readFloat() throws IOException;
    double readDouble() throws IOException;
    String readLine() throws IOException;
    String readUTF() throws IOException;
}

RandomAccessFile的构造函数:

RandomAccessFile(File file, String mode):创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。
RandomAccessFile(String name, String mode):创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。

RandomAccessFile在继承和实现了DataInput和DataOutput的基础上增加了自己的方法:
FileChannel    getChannel():返回与此文件关联的唯一 FileChannel 对象。
FileDescriptor    getFD():返回与此流关联的不透明文件描述符对象。
long    getFilePointer():返回此文件中的当前偏移量。
void     seek(long pos):设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。
void     setLength(long newLength):设置此文件的长度。

    public static void randomAccessFileTest() throws IOException{
        //RandomAccessFile使用于大文件的读取
        RandomAccessFile randomAccessFile = new RandomAccessFile("C:\\Users\\haisui\\Desktop\\testIo2.txt","rw");
        randomAccessFile.writeBytes("hello world");
        randomAccessFile.writeBoolean(false);
        randomAccessFile.writeUTF("你好!");

        randomAccessFile.seek(12);//跳过hello world
        boolean booleanRead = randomAccessFile.readBoolean();
        System.out.print("读取boolean:" + booleanRead);
        randomAccessFile.seek(0);
        String firstLine = randomAccessFile.readLine();
        System.out.print("指针移动到第一个字节读取一行:" + firstLine);
        randomAccessFile.readBoolean();
        String utfRead = randomAccessFile.readUTF();
        System.out.print("读取字符:" + utfRead);

    }
时间: 2024-10-25 08:44:56

java中的IO基础总结的相关文章

Java中的IO基础学习小记之一

IO流用来处理设备间的数据传送 Java对数据的操作是通过流的方式进行的 Java用于操作流的对象都在io包中 数据按照操作数据的方式分为两种:字节流和字符流 流按照流向分为:输入流和输出流 硬盘存储的数据时间长,断电后仍然存在 内存存数的数据时间短,断电后不存在. 硬盘读写数据慢,内存读取数据快 Java中IO的输入和输出是相对于内存的 从硬盘向内存中写数据,称为输入 从内存向硬盘中写数据,称为输出 外围设备包括  打印机,硬盘,U盘等 在计算机中,所有的数据都是按照二进制的形式存储的. 用于

Java中的IO流

Java中的IO流是实现输入/输出的基础. 按照流的方向不同:分为输入流和输出流. 按照处理数据单位的不同:分为字节流(8位)和字符流(16位). 按照功能不同:分为节点流和处理流 所有面向字节的流类都继承于InputStream类(输入流) 或OutputStream类(输出流),这两个类是抽象类,我们可以利用它的子类来完成不同的功能. InputStream.OutputStream都是抽象类 InputStream抽象了应用程序读取数据的方式 OutputStream抽象类应用程序写出数据

Java中String的基础知识

Java中String的基础知识 ==与equal的区别 基本数据类型,指的是java中的八种基本数据结构(byte,short,char,int,long,float,double,boolean),一般的比较是使用的 ==,比较的是他们的值. 复合数据类型(类) ==比较的是两个对象的引用,可以理解为在内存中的地址,除非是同一个new出来的对象,他们的 ==为true,否则,都为false. equal是object中的方法.object中的实现如下,内部还是使用==实现,也就是说,如果一个

JAVA中各种IO的关系及说明

JAVA中的IO以前看着太混乱了,现在梳理一下 1.IO流分为两大类,一个是以stream结尾的,叫做字节流,顾名思义,按照byte为单位进行传输:另一种是以reader和writer结尾的叫做字符流,它貌似是封装了stream结尾的 IO流类,而产生的另一种功能类似,但是传输介质不再是byte,而是字符,也就是说,根据传说字符的不同,比如UTF-8,GBK等,它的传输单位也不是固定的. 2.输入输出,输入指的是从文件向内存中进行读入,输出指的是,内存中的内容写出到文件中 3.常见的Buffer

Java中的IO流总结

Java中的IO流总结 1. 流的继承关系,以及字节流和字符流. 2. 节点流FileOutputStream和FileInputStream和处理流BufferedInputStream和BufferedOutputStream.以及对应的FileOutputWriter,FileInputReader,BufferedInputReader,BufferedOutputWriter. 3. 转换流InputStreamReader和OutputStreamWriter 一:流的继承关系 字节

Java中的IO流之输入流|乐字节

亲爱的乐字节的小伙伴们,小乐又来分享Java技术文章了.上一篇写到了IO流,这篇文章着重 谈谈输入流,再下次再说输出流. 点击回顾上一篇:乐字节Java之file.IO流基础知识和操作步骤 一. 输入流 字节流和字符流的操作方式几乎完全一样,只是操作的数据单元不同而已 .字节流可 以操作所有文件,字符流仅操作纯文本. 1.抽象类:InputStream 和 Reader InputStream和Reader是所有输入流的基类,它们是两个抽象类,是所有输入流的模版,其中定义的方法在所有输入流中都可

Java NIO之Java中的IO分类

前言 前面两篇文章(Java NIO之理解I/O模型(一).Java NIO之理解I/O模型(二))介绍了,IO的机制,以及几种IO模型的内容,还有涉及到的设计模式.这次要写一些更贴近实际一些的内容了,终于要说到了Java中的各种IO了.我也是边学边理解,有写的不对的地方,欢迎小伙伴们指出和补充. Java中的IO分类 BIO BIO是指 Blocking IO 在JDK1.0的时候就引入了,直到JDK1.4一直都是Java中唯一的IO方式.它的主要实现方式就是,一个线程执行一个请求,如果请求数

JAVA 中的IO流

Java中的IO流是用来处理设备与设备之前的数据传输,在java中以流的形式传输.流分为两类:字节流和字符流. 字节流:InputStream,OutPutSteam.(计算机内的数据都是以字节存储的,字节流可以操作任意数据) 字符流:Reader,Writer.(字符流只能操作字符,但是在实际应用中字符流比较方便) 从操作来看又可以分为:输入流和输出流. 在进行IO流操作的时候分为以下几步:1.导入IO流的包,2.进行IO流的异常处理,3.关闭IO流释放资源. 字节流 ————————————

java中的io系统详解

java中的io系统详解 分类: JAVA开发应用 笔记(读书.心得)2009-03-04 11:26 46118人阅读 评论(37) 收藏 举报 javaiostreamconstructorstringbyte 相关读书笔记.心得文章列表 Java 流在处理上分为字符流和字节流.字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符.字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组. Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他