Java IO笔记

 

一、概念

Java中对文件的操作是以流的方式进行的。流是Java内存中的一组有序数据序列。Java将数据从源(文件、内存、键盘、网络)读入到内存中,形成了流,然后将这些流还可以写到另外的目的地(文件、内存、控制台、网络),之所以称为流,是因为这个数据序列在不同时刻所操作的是源的不同部分。

 

二、分类

流分类的方式很多:

1、按照输入的方向分,输入流和输出流,输入输出的参照对象是Java程序。

2、按照处理数据的单位不同分,字节流和字符流,字节流也称为原始数据,需要用户读入后进行相应的编码转换。而字符流的实现是基于自动转换的,读取数据时会把数据按照JVM的默认编码自动转换成字符。字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)。

3、按照功能的不同分,分节点流和过滤流,节点流是直接从一个源读写数据的流(这个流没有经过包装和修饰),过滤流是在对节点流封装的基础上的一种流,FileInputStream是一个节点流,可以直接从文件读取数据,但是BufferedInputStream可以包装FileInputStream,使得其有缓冲功能。

其实除了以上三种分类外,还有一些常常听到的一些分类比如:对象流、缓冲流、压缩流、文件流等等。其实都是节点流和过滤流的子分类。当然你也可以创建新的流类型,只要你需要。

 

三、流分类的关系

不管流的分类是多么的丰富和复杂,其根源来自于四个基本的类。这个四个类的关系如下:

--------------------------------------------------------------------------------------------------------
                           字节流                      字符流
--------------------------------------------------------------------------------------------------------
输入流             InputStream             Reader
--------------------------------------------------------------------------------------------------------
输出流            OutputStream            Writer
--------------------------------------------------------------------------------------------------------

四、字节流和字符流的相互转换

1、从字节流到字符流:InputStreamReaderOutputStreamWriter类可以实现。

2、从字符流到字节流:可以从字符流中获取char[]数组,转换为String,然后调用StringAPI函数getBytes() 获取到byte[],然后就可以通过ByteArrayInputStreamByteArrayOutputStream来实现到字节流的转换。

 

㈠字节流处理概述:

对于字节流处理的类都继承自InputStreamOutputStream这两个抽象类。

InputStream提供的最重要的方法是:

 read();   

 read(byte[] b) ;   

 read(byte[] b, int off, int len) ;  

用于从输入流中读取字节。

其它方法:

     long skip(long n) :在输入流中跳过n个字节,并返回实际跳过的字节数。

      int available() :返回在不发生阻塞的情况下,可读取的字节数。

      void close() :关闭输入流,释放和这个流相关的系统资源。

      void mark(int readlimit) :在输入流的当前位置放置一个标记,如果读取的字节数多于readlimit设置的值,则流忽略这个标记。

      void reset() :返回到上一个标记。

      boolean markSupported() :测试当前流是否支持mark和reset方法。如果支持,返回true,否则返回false。  

OutputStream提供的最重要的方法是:

write(int b); 
write(byte[] b);
write(byte[] b, int off, int len)

用于将字节写入输出流。

 

字节流的处理类有很多,他们都继承自InputStream或者OutputStream抽象类。

①输入流:

先谈谈输入流,输入流中跟数据源直接接触的类有:FileInputStreamByteArrayInputStream,他们分别实现了从文件或者内存中的字节数组读入数据到输入流。

其他的输入流处理类都是装饰类(Decorator模式),下面对他们进行一下简单介绍:

BufferedInputStream: 提供了缓冲功能。

DataInputStream: 允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。

PipedInputStream: 允许以管道的方式来处理流。当连接到一个PipedOutputStream后,它会读取后者输出到管道的数据。

PushbackInputStream: 允许放回已经读取的数据。

SequenceInputStream: 能对多个inputstream进行顺序处理。

②输出流:

基本上每个输入流类都有一个相应的输出流类,提供相应的输出流处理。

同样,跟数据目的地直接接触的类有:FileOutputStreamByteArrayOutputStream,前者实现了把数据流写入文件的功能,后者实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

下面对其它的装饰类做一下简单介绍:

BufferedOutputStream: 提供了缓冲功能的输出流,在写出完成之前要调用flush来保证数据的输出。

DataOutputStream: 数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

PipedOutputStream: 允许以管道的方式来处理流。可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。

PrintStream: 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。我们经常用到的System.out或者System.err都是PrintStream。

 

㈡字符流处理概述:

所有的字符流操作类都继承自Reader或者Writer这两个抽象类。

Reader提供的重要方法有:

read(char[] cbuf);   

read(char[] cbuf, int off, int len);   

read(CharBuffer target);  

他们提供了从流中读取数据到字符数组或者CharBuffer的功能。

Writer提供的重要方法有:

 write(char[] cbuf);   

 write(char[] cbuf, int off, int len);   

 write(int c);   

 write(String str);   

 write(String str, int off, int len); 

他们提供了把字符、字符数组或者字符串写入流中的功能。

 

①输入流

跟数据源直接接触的类:

CharArrayReader: 从内存中的字符数组中读入数据,以对数据进行流式读取。

StringReader:从内存中的字符串读入数据,以对数据进行流式读取。

FileReader:从文件中读入数据。注意这里读入数据时会根据JVM的默认编码对数据进行内转换,而不能指定使用的编码。所以当文件使用的编码不是JVM默认编码时,不要使用这种方式。要正确地转码,使用InputStreamReader。

装饰类:

BufferedReader:提供缓冲功能,可以读取行:readLine();

LineNumberReader: 提供读取行的控制:getLineNumber()等方法。

InputStreamReader: 字节流通向字符流的桥梁:它使用指定的 charset读取字节并将其解码为字符。

②输出流:

根数据目的相关的类:

CharArrayWriter:把内存中的字符数组写入输出流,输出流的缓冲区会自动增加大小。输出流的数据可以通过一些方法重新获取。

StringWriter: 一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。

FileWriter:把数据写入文件。

装饰类:

BufferedWriter:提供缓冲功能。

OutputStreamWriter:字符流通向字节流的桥梁:可使用指定的 charset将要写入流中的字符编码成字节。

PrintWriter: 向文本输出流打印对象的格式化表示形式。

流处理中其他方法:

mark和reset用于重复读取某段的数据。

Writer或者OutputStream中的flush(): 刷新该流的缓冲,用于确保数据的输出。

close(): 关闭流并释放与之关联的所有系统资源。

Java I/O库的设计原则

        Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。

        这种机制实际上是一种被称为Decorator(装饰)设计模式的应用。

        通过流的链接,可以动态的增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。

      我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不太容易掌握的原因,但在I/O库中Decorator模式的运用,给我们提供了实现上的灵活性。

 

对象序列化

        将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化。

        将一个对象保存到永久存储设备上称为持续性。

       一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。

Serializable接口中没定义任何的方法, 使用ObjectOutputStream, ObjectInputStream进行对象序列化.,调用的方法是writeObject(object),反序列化,readObject(object)

 

 本文也谈不上是原创,只是自己在学习的过程中,把好几个版本的笔记整合到一起~~~,然后又不好写转载(谁的),就暂且归到原创~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值