第18章 I/O系统

20170707 IO部分和NIO部分感觉讲的有点不太好理解,没有细看。有一篇博客讲的挺详细的,有时间可以去瞅瞅 http://www.cnblogs.com/rollenholt/archive/2011/09/29/2195730.html

  • 18.2 输入和输出

编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象。“流”屏蔽了实际的I/O设备中处理数据的细节。

通过继承,任何自Inputstream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写入单个字节或者字节数组。

  • 18.2.1 InputStream类型

InputStream的作用是用来表示那些从不同数据源产生的输入的类。包括

名称功能
字节数组ByteArrayInputStream允许将内存的缓冲区当做InputStream
String对象StringBufferInputStream将String转换成InputStream
文件FileInputStream用户从文件中读取信息
管道,工作方式与实际管道相似,即从一端输入,从另一端输出PipedInputStream产生用于写入相关PipedOutputStream的数据,实现管道化概念
合并流SequenceInputStream将两个或多个InputStram对象转成单一InputStram
抽象类,作为装饰器的接口FilterInputStream抽象类,作为装饰器的接口

一个PipedInputStream的例子

http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html

一个SequenceInputStream的例子

  • 18.2.2 OutputStream类型

决定了输出所要去往的目标:字节数组、文件或者管道

功能
ByteArrayOutputStream在内存中创建缓冲区,所有送往“流”的数据都要放置在此缓冲区
FileOutputStream用于将信息写至文件
PipedOutputStream任何写入其中的信息都会自动作为相关PipedInputStream的输出。实现管道化概念
FilterOutputStream抽象类,作为“装饰器”的接口
  • 18.4 Reader和Writer

InputStream和OutputStream在以面向字节形式的I/O中仍可以提供极有价值的功能,Reader和Writer则提供兼容Unicode与面向字符的I/O功能。另外:
1. Java 1.1向InputStream和OutputStream继承层次结构中添加了一些新类,所以显然这两个类是不会被取代的
2. 如何将面向字节和面向字符结合起来用?为了实现这个目的,要用到“适配器”类:InputStreamReader可以把InputStream转换成Reader,而OutputStreamWriter可以把OutputStream转换成Writer

设计Reader和Writer继承层次结构主要是为了国际化。老的I/O流继承层次结构仅支持8位字节流,并且不能很好地处理16位的Unicode字符。由于Unicode用于字符国际化(Java背身char也是16位的Unicode),所以添加Reader和Writer继承层次结构就是为了在所有的I/O操作中都支持Unicode。另外,新类库的设计使得它的操作比旧类库更快。

字符流使用

 字符流与字节流互转:(这里会涉及到编码问题,字符到字节需要编码,字节到字符需要解码,可以查看https://www.ibm.com/developerworks/cn/java/j-lo-javaio/index.html
  •  18.8.3 标注I/O重定向

标准I/O模型中,Java提供了System.in、System.out和System.err。其中,System.out和System.err已经被包装成了PrintStream,可以直接使用,但是System.in却是InputStream,使用之前必须对其进行包装。

如果不想直接在显示器上进行输出,而是希望在文本中进行输出,那么可以对这些标准I/O进行重定向:

通道和缓冲器

  • 18.10.6 内存映射文件

比较nio可以更加显著地加快速度,允许我们创建和修改那些因为太大而不能放入内存的文件

  • 18.12 对象序列化

Java的对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象(通过ObjectOutputStream和ObjectInputStream来实现)。

对象序列化的概念加入到语言中是为了支持两种主要特性。一个是Java的远程方法调用(Remote Method Invocation,RMI),另一个对于Java Beans来说,对象的序列化也是必须的。

对象序列化特别“聪明”的一个地方是它不仅保存了对象的“全景图”,而且能追踪对象内所包含的所有引用,并保存那些对象;接着又能对对象内包含的每个这样的引用进行追踪;以此类推。

在对一个Serializable对象进行还原的过程中,没有调用任何构造器,包括默认的构造器。整个对象都是通过从InputStream中取得数据恢复而来的。

  • 18.12.1 寻找类

将一个对象从它的序列化状态中恢复出来,必须要保证Java虚拟机能找到相关的.class文件。否则会抛出ClassNotFoundException的异常。

  • 18.12.2 序列化的控制

如果有特殊的需求,可以通过实现Externalizable接口代替实现Serializable接口,来对序列化过程进行控制。

在恢复b2的时候报错,因为Blip2的构造器不是public的。

对于Serializable对象,对象完全以它存储的二进制位为基础来构造,而不调用构造器。而对于一个Externalizable对象,所有普通的默认构造器都会被调用(包括在字段定义时的初始化),然后调用readExternal()。

如何完整保存和恢复一个Externalizable对象:

如果注释掉跟随于“You must do this”后面的两行代码,那么还原后,s是null,而i是0.

transient关键字
如果我们操作的是一个Serializable对象,那么所有序列化都会自动进行。为了能够进行控制,可以用transient关键字指定字段关闭序列化。例如保存某个特定的登录会话信息,但是不包括密码

由于Externalizable对象在默认情况下不保存它们的任何字段,所以transien关键字只能和Serializable对象一起使用

Externalizable的替代方法

实现Serializable接口,并添加名为writeObject()和readObject()的方法。(是添加,不是覆盖或者实现,因为这两个方法不是接口中定义的,而且是私有方法

调用defaultWriteObject()和defaultReadObject()可以调用默认的写和读:

o.writeObject(sc);会检查sc判断它是否拥有自己的writeObject()方法,如果有,那么就会直接使用它。同理对于readObject()。

  • 18.12.3 使用“持久性”

Serializable对象的序列化和反序列化可以实现对象的“深度复制”(即复制整个对象网,而不是仅仅是基本对象及其引用):

只要将任何对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网。

静态变量(static字段修饰的)不会序列化,需要自己动手去实现。

Line.serializeStaticState(out);就是自己实现static值。

  • 18.13 XML

没有细看,自己网上找了下DOM与SAX的区别:

In SAX, events are triggered when the XML is being parsed. When the parser is parsing the XML, and encounters a tag starting (e.g. ), then it triggers the tagStarted event (actual name of event might differ). Similarly when the end of the tag is met while parsing (), it triggers tagEnded. Using a SAX parser implies you need to handle these events and make sense of the data returned with each event.

In DOM, there are no events triggered while parsing. The entire XML is parsed and a DOM tree (of the nodes in the XML) is generated and returned. Once parsed, the user can navigate the tree to access the various data previously embedded in the various nodes in the XML.

In general, DOM is easier to use but has an overhead of parsing the entire XML before you can start using it.

SAX是事件驱动的,解析效率高,不将整个文档载入内存中,占用内存少,不过不能写入XML。

DOM是将整个文档树在内存中,便于操作,支持删除、修改、重新排序等,但是将整个文档放入内存,浪费时间和空间

  • 18.14 Preferences

它只能用于小的、受限的数据集合–我们只能存储基本类型和字符串,并且每个字符串的存储长度不能超过8K。

Preferences存储的数据在哪里呢?Windows是存在注册表中的

http://support.inqscribe.com/knowledgebase/articles/14405-how-do-i-find-my-preferences-file

Telegram频道已经开通,关注flyzythink,随手分享正能量,了解VPS优惠与补货
Telegram群组已经开通,加入flyzy小站,FREE TO TALK
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注