- 浏览: 25100 次
- 性别:
- 来自: 上海
文章分类
最新评论
Java IO 用的是‘decorator模式’来构建的。要容易理解Java IO 应该从对称性和两个模式(装饰器模式和适配器模式)这两方面进行分析。
装饰器模式:
在由InputStream、OutputStream、Reader和Writer 代表的等级结构内部,有一些流处理器可以对另外一些流处理器起到装饰作用,形成新的、具有改善了的功能的流处理器。
下面是Decorator模式的结构图:
1.Component就是装饰器模式中公共方法的类,在装饰器模式结构图的顶层。
2.ConcreateComponent是转换器模式中具体的被装饰的类,IO包中的媒体流就是此种对象。
3.Decorator装饰器模式中的核心对象,所有具体装饰器对象的父类,完成装饰器的部分职能。在上面的例子中Decorator类和这里的对应。该类可以只做一些简单的包裹被装饰的对象,也可以还包含对Component中方法的实现……他有一个鲜明的特点:继承至Component,同时包含一个Component作为其成员变量。装饰器模式动机中的动态地增加功能是在这里实现的。
4.ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰器对象,他们完成具体的装饰功能。装饰功能的实现是通过调用被装饰对象对应的方法,加上装饰对象自身的方法。这是装饰器模式动机中的添加额外功能的关键。
装饰器模式相关知识参考http://miaoxiaodong78.blog.163.com/blog/static/18765136200701232434996/
适配器模式:
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 比如ByteArrayInputStream 是一个适配器类,它继承了InputStream,而封装了一个byte数组,换句话说,它将以个byte数组的接口适配成InputStream流处理器的接口。
适配器的结构图:
适配器相关的知识参考:http://www.cnblogs.com/houleixx/archive/2008/03/04/1090214.html
下面开始了解Java IO
Java IO 中的流从不同的角度可以分成三类:
1、按数据流的方向不同可以分为输入流(InputStream/Reader)和输出流(OutputStream/Writer),用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往往输出流写,而不能读取。
2、按处理数据单位不同可以分为字节流(InputStream/OutputStream-8位)和字符流(Reader/Writer-16位)。
3、按功能不同可以分为节点流(原始流)和处理流(链接流)。节点流为可以从一个特定的数据源(节点)读写数据(如文件、内存)。处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
下面的分析是从功能上来分析的:
字节流处理类概述:
对于字节流处理的类都继承自InputStream和OutputStream这两个抽象类。
InputStream
InputStream结构图,从图中可以很清楚的看到装饰器模式的应用。
InputStream提供的最重要的方法是:
read(); read(byte[] b) ; read(byte[] b, int off, int len) ;
用于从输入流中读取字节。
原始流(也是一个适配器类):
(1)ByteArrayInputStream:为多线程的通信提供缓冲区操作,接收一个Byte数据作为流的源。
(2)FileInputStream:建立一个与文件有关的输入流。接收一个File对象作为流的源。
(3)PipedInputStream:可以与PipedOutputStream配合使用,用于读入一个数据管道的数据,接收一个PipedOutputStream 作为源。
(4)StringBufferInputStream:将一个字符串缓冲区转换为一个输入流。接收一个String对象作为流的源。
链接流:
(1)FilterInputStream称为过滤输入流,它将另外一个输入流作为流源。这个类的子类包括一下几种。
BufferedInputStream: 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。
DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
LineNumberInputStream(已过时):提供带有行计数功能的过滤输入流。
PushbackInputStream:提供特殊的功能,可以将已经读取的字节“推回”到输入流中。
(2)ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化
(3)SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
从结构图中可以看出直接引用InputStream(相当于装饰器模式中的Component) 的类就是链接流了。而FilterInputStream 相当于装饰器模式中的Decorator。以下的也是一样,所以就不一一分析了,其类的功能可查看API 文档。
OutputStream(和InputStream相对应)
OutputStream结构图:
OutputStream提供的最重要的方法是:
write(int b); write(byte[] b); write(byte[] b, int off, int len)
用于将字节写入输出流。
字符流处理概述:
所有的字符流操作类都继承自Reader或者Writer这两个抽象类。
Reader
Reader结构图:
Reader提供的重要方法有:
read(char[] cbuf); read(char[] cbuf, int off, int len); read(CharBuffer target);
他们提供了从流中读取数据到字符数组或者CharBuffer的功能。
Writer
Writer结构图:
Writer提供的重要方法有:
- write(char[] cbuf);
- write(char[] cbuf, int off, int len);
- write(int c);
- write(String str);
- write(String str, int off, int len);
write(char[] cbuf); write(char[] cbuf, int off, int len); write(int c); write(String str); write(String str, int off, int len);
他们提供了把字符、字符数组或者字符串写入流中的功能。
字节流和字符流之间的转换(从字节流适配到字符流)
InputStreamReader和OutputStreamReader:把一个以字节为导向的stream转换成一个以字符为导向的stream。
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集 。
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
RandomAccessFile
RandomAccessFile:此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
I/O应用的例子
- package JavaIO;
- import java.io.*;
- public class JavaIO{
- public static void main(String[] args) throws Exception {
- // 1b. 接收键盘的输入
- /*
- * 由于想以缓存字节读取方式从标准IO(键盘)中读取数据,所以要
- * 先把标准IO(System.in)转换成字符导向的stream,再进行BufferedReader封装。
- */
- BufferedReader stdin = new BufferedReader(new InputStreamReader(
- System.in));
- System.out.println("Enter a line:");
- System.out.println(stdin.readLine());
- // 2. 从一个String对象中读取数据
- /*
- * 要以字符的形式从一个String对象中读取数据,所以要产生一个StringReader类型的stream。
- */
- StringReader in2 = new StringReader("zhxing");
- int c;
- while ((c = in2.read()) != -1)
- System.out.println((char) c);
- in2.close();
- // 3. 从内存取出格式化输入
- // 把内存中的一个缓冲区作为DataInputStream使用
- try {
- DataInputStream in3 = new DataInputStream(new ByteArrayInputStream(
- "zhxing".getBytes()));
- while (true)
- System.out.println((char) in3.readByte());
- } catch (EOFException e) {
- System.out.println("End of stream");
- }
- // 4. 输出到文件
- /*
- * 对String对象s2读取数据时,先把对象中的数据存入缓存中,再从缓冲中进行读取;对TestIO.out文件进行操作时,
- * 先把格式化后的信息输出 到缓存中,再把缓存中的信息输出到文件中。
- */
- try {
- BufferedReader in4 = new BufferedReader(new StringReader("zhxing"));
- PrintWriter out1 = new PrintWriter(new BufferedWriter(
- new FileWriter("F:\\java\\ TestIO.out")));
- int lineCount = 1;
- String s = null;
- while ((s = in4.readLine()) != null)
- out1.println(lineCount++ + ":" + s);
- out1.close();
- in4.close();
- } catch (EOFException ex) {
- System.out.println("End of stream");
- }
- // 5. 数据的存储和恢复
- /*
- * 对Data.txt文件进行输出时,是先把基本类型的数据输出屋缓存中,再把缓存中的数据输出到文件中;对文件进行读取操作时,先把文件中的数据读取到缓存中,再从缓存中以基本类型的形式进行读取。注意in5.readDouble()这一行。因为写入第一个writeDouble(),所以为了正确显示。也要以基本类型的形式进行读取。
- */
- try {
- DataOutputStream out2 = new DataOutputStream(
- new BufferedOutputStream(new FileOutputStream(
- "F:\\java\\ Data.txt")));
- out2.writeDouble(3.1415926);
- out2.writeChars("\nThas was pi:writeChars\n");
- out2.writeBytes("Thas was pi:writeByte\n");
- out2.close();
- DataInputStream in5 = new DataInputStream(new BufferedInputStream(
- new FileInputStream("F:\\java\\ Data.txt")));
- BufferedReader in5br = new BufferedReader(
- new InputStreamReader(in5));
- System.out.println(in5.readDouble());
- System.out.println(in5br.readLine());
- System.out.println(in5br.readLine());
- } catch (EOFException e) {
- System.out.println("End of stream");
- }
- // 6. 通过RandomAccessFile操作文件
- // 通过RandomAccessFile类对文件进行操作。
- RandomAccessFile rf = new RandomAccessFile("F:\\java\\ rtest.dat", "rw");
- for (int i = 0; i < 10; i++)
- rf.writeDouble(i * 1.414);
- rf.close();
- rf = new RandomAccessFile("F:\\java\\ rtest.dat", "r");
- for (int i = 0; i < 10; i++)
- System.out.println("Value " + i + ":" + rf.readDouble());
- rf.close();
- rf = new RandomAccessFile("F:\\java\\ rtest.dat", "rw");
- rf.seek(5 * 8);
- rf.writeDouble(47.0001);
- rf.close();
- rf = new RandomAccessFile("F:\\java\\ rtest.dat", "r");
- for (int i = 0; i < 10; i++)
- System.out.println("Value " + i + ":" + rf.readDouble());
- rf.close();
- }
- }
相关推荐
Java输入输出流及文件读写详解;Java输入输出流及文件读写详解。
详细介绍java各种输入输出流对象及其使用方法,并有实际例子帮助理解
Java的输出输出流详解及输入输出实例 文件的基本操作
Java_输入输出流及文件读写详解
Java_输入输出流及文件读写详解
主要介绍了Java输入输出流,结合实例形式详细分析了Java常见的输入输出常用操作技巧与相关注意事项,需要的朋友可以参考下
主要介绍了Java输入/输出流体系详解,涉及字节流和字符流,输入输出体系,转换流,以及文件的读写等相关内容,具有一定参考价值,需要的朋友可以了解下。
Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。此外,Java也对块传输提供支持,在核心库java.nio中采用的便是块IO。关于NIO我们在后面还有专门的讨论。 流IO的好处是简单...
下面小编就为大家带来一篇Java和C#输入输出流的方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
一、文件的编码 开发时一定要注意项目默认的编码!!!!!!!! 文件操作的时候一定要记得关闭!... ASCII:美国标准信息交换码,用一个字节的7位可以表示一个字符 ISO8859-1:拉丁码表,西欧标准字符集,...
Java中的流分为两种,一种是字节流,另一种是字符流。这篇文章主要介绍了JAVA中输入输出流的相关资料,需要的朋友可以参考下
java输入输出,java中的重难点详解,记得好评哦
ByteArrayInputStream和ByteArrayOutputStream分别集成自InputStream和OutputStream这两个输入和输出流,这里我们就来详解Java中ByteArray字节数组的输入输出流的用法,需要的朋友可以参考下
java数据流概述和java。io包,文件输入输出
详细讲解了java各种输入输出流(stream),以及serialization和externalization的用法与关系
《Java程序设计》共分12章,内容包括Java语言概述、面向对象编程初步、Java的基本语法、类库与数组、面向对象编程深入、图形用户界面编程、异常处理和输入输出,以及多线程编程等内容。 本书讲解Java程序设计知识...
简单的介绍了java中关于输入和输出 流的相关概念,通俗易懂。
详细介绍了java.io输入输出流,以及常用到的方法
JAVA-IO是输入输出流,很重要的java基础哦
在Java中,IO(输入/输出)是程序与外部世界进行交互的重要桥梁,而NIO(非阻塞IO)则是Java IO的一个重要扩展,它提供了更为高效、灵活的数据处理方式。 传统的Java IO是阻塞式的,即当程序进行读写操作时,如果...