`
bsr1983
  • 浏览: 1100886 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多
12.1 流
在Java程序设计语言中,一个可以读取字节序列的对象被称为输入流(input stream)。一个可以写入字节序列的对象被称为输出流(output stream)。在抽象类InputStream和OutputStream中对它们进行了说明。由于以字节为单位的流处理存储为Unicode码的信息很不方便,所以有一个专门的类层次来处理Unicode字符,这些类继承与抽象类Reader和Writer。它们的读写操作都是基于双字节的Unicode代码单元,而不是基于单字节。
不论是read方法还是write方法都能阻塞(block)一个线程直到自己被真正地读取或者写入。
这意味着如果流不能立即被读取或者写入(通常是因为网络连接繁忙),Java就会挂起这个调用的线程。这样就能够给其他线程提供机会去做有用的工作,同时这个方法将一直等待,直到流再次可用为止。
available方法能够检查目前可以读取的字节数。
12.2 完整的流结构
12.2.1 流过滤器的分层
FileInputStream和FileOutputStream能够把输入和输出流与磁盘文件关联起来。要想达到这一目的,只需要在构造器中给出文件名或者文件的具体路径名即可。
提示:因为所有在java.io中的类都是将相对路径名解释为起始于用户的当前工作目录,所以应该清楚当前的目录。可以通过调用System.getProperty("user.dir")来获得。
Java使用了一种很聪明的策略来划分这两种职责。一些流(例如FileInputStrean以及URL类中利用openStream方法来返回的输入流)可以从文件以及其他地方接收字节。另一些流(例如DataInputStram和PrintWiter)可以将字节组合成更加有用的数据类型。Java程序员采用将一个已经存在的流传递给另一个流的构造器方法,将这两种流结合起来,结合后的流被称为过滤流(filetered stream)。
总而言之,处理需要使用怪异的构造器对流进行分层之外,能够将流进行混合与匹配时Java非常实用的特性之一!
12.2.2 数据流
数据流支持读取所有Java基本类型的方法。
注意:依赖于所使用的平台,在内存中有两种方法存储整数和浮点数。假设正在使用4字节的整数,他的十进制数值为1234或者用十六进制表示为4D2,那么能够使用这种方式来存储。一种是内存中的四个字节的第一个字节用来存储最高有效字节(MSB),值为00 00 04 D2。这也被称为高字节前存法;另一种是从最低字节(LSB) 开始,值为D2 04 00 00。这种更加自然的方法称为低字节前存法。例如,SPARC使用的是高字节前存方法,奔腾使用的是低字节前存方法。这样一来就会出问题。当一个C或C++文件存储时,数据保持方式和处理器存储它们的方式一样,这样一来,即使把一个最简单的数据文件从一个平台移动到另一个平台都会遇到挑战。在Java中,不管在什么处理器上,所有的值都是采用高字节前存的方法存储的。这就使得Java的数据文件具有平台独立性。
注意:二进制数据格式是紧凑的并与平台无关。除了UTF字符串以外,其他的都可以随机存取,其主要的缺点是这些二进制文件不适合人们阅读。
12.2.3 随机存取文件流
RandomAccessFile流泪能够在文件的任何位置查找或者写入数据。它同时实现了DataInput和DataOutput接口。磁盘文件可以随机存取,但是来自网络的数据流就不行了。打开一个随机存取文件,要么进行制度操作,要么进行读写操作。可以通过构造器的第二个参数带入“r”(读取)或“rw”(读写)指定相应的操作。
当打开一个向右文件作为RandomAccessFile时,原来的文件不会被删除。
随进存取文件同时提供了一个文件指针(file pointer)。文件指针总是指向下一条要进行读取操作记录的位置。Seek方法将文件指针设定在文件内部的任意字节位置。Seek使用的参数是一个在0到文件长度(以字节计)之间的long整数。
12.2.4 文本流
Java提供了一套六过滤器作为Unicode字符码和本地操作系统使用的字符码间的桥梁。所有这些类都从抽象类Reader和Writer类派生出来,而名字会令人联想到用于二进制数据的名字。
12.2.5 字符集
字符集给出了双字节Unicode码序列与在本地字符编码中采用的字节序列间的映射。
字符集的名称不分大小写。
可以用官方名称或者任何一个别名调用静态方法forName来获得Charset:
Charset cset=Charset.forName("ISO-8859-1");
12.2.6 文本输出
进行文本输出时,应该使用PrintWriter。print writer可以以文本格式打印字符串和数值。与DataOutputStream类似,尽管提供了一些很有用的输出方法,但却没有定义目的地,一个PrintWriter必须与一个目标writer相结合。
12.2.7 文本输入
当以二进制格式写入数据时,应当使用DataOutputStream。
当以文本格式写入数据时,应当使用Printriter。
提示:Java的StringReader和StringWriter类可以像对待一个数据流一样对待字符串。这对于想要使用相同的代码从流中分析字符串和数据来说十分有用。
12.3 ZIP文件流
注意:处理ZIP文件的类在java.util.zip中而不在java.io中,所以请记住要添加必要的import语句。尽管不是java.io的一部分,但GZIP和ZIP类还是java.io.FilterInputStream和java.io.FilterOutPutStream的子类。java.util.zip包同样也包含了拥有计算循环冗余码校验(Cyclic Readundancy Check,CRC)的类。(CRC是用来生成类似散列码的方法,文件接收者可以使用这些来检验数据的完整性。)
12.4 流的使用
12.4.1 分隔符输出
12.4.2 字符串记号处理器和带分隔符的文本
java.util.StringTokenizer
12.4.3 读取带分隔符的输入
12.4.4 StringBuilder类
StringBuilder的工作过程更像一个ArrayList。它管理着一个可以根据需求增长或缩短的字符数组char[]。可以追加、插入或者删除代码单元,直到StringBuilder中含有的所希望的字符为止,然后使用toString方法将内同转换为一个真正的String对象。
注意:StringBuilder类是JDK5.0新引入的。它的前身StringBuffrt的效率稍稍低一点,但是却可以允许多线程进行增加或移除字符操作。如果所有的字符串编辑出现在一个线程中,应该使用StringBuilder。这两个类的API都是相同的。
12.4.5 随机存取流
12.5 对象流
12.5.1 存储可变类型的对象
12.5.2 理解对象序列化文件格式
对象序列化使用的是一种特殊的文件格式来存储对象。
Java从以下途径获得指纹:
首先用标准的方式对类、超类、接口、域类型和方法签名的描述进行排序。
然后对那些数据应用一种所谓的“安全散列算法”(Secure Hash Algorithm,SHA)
SHA是一种可以从大块的信息块中获取“指纹”的快速算法。不管原始数据多大,这种方法产生的指纹必然是一个长度为20字节的数据包。
注意:从技术上说,只要类的数据布局没有改变,都回一个对象就是安全的。但是,Java相对的保守,所以还会检查方法是不是被改变。(毕竟,方法描述了所保存的数据的意义。)当然,实际上,类是不断衍化的,所以成像读取对象的老版本也是必要的。
12.5 保存对象引用问题的解决
Java使用序列化(serialization)方法。这就是所谓的对象序列化(object serialization)机制。下面是具体的算法:
所有保存到磁盘的对象都有一个序列号。
当向磁盘存储一个对象时,先检查相同的对象是否已经保存。
如果已经存储过,只要写入“与已经存储的对象具有序列号X”。如果没有,保存所有的数据。
12.5.4 理解对象引用的输出格式
所有的对象(包括数组和字符串)以及类描述符在保持到输出文件时,都会获得一个序列号。因为每个保存的对象都会分配到一个唯一的序列号(从00 7E 00 00开始),这个处理流程被称为序列化(serralization).
通常,不必知道准确的文件格式(除非想尝试通过改变数据创造一个遗憾的效果。)应该记住下面这些:
对象流的输出包含所有对象的类型和数据域。
每个对象都会分配一个序列号。
重复出现的同一个对象会存储为其序列号的引用。
12.5.5 修改默认的序列化机制
Java有一个简单的机制用来避免这些域被序列化,即使用关键字transient标注他们。另外,还需要将那些属于非序列化中的域标注为transient。当对象被序列化时,标注为transient的域是会被跳过的。
提示:序列化有些慢,因为虚拟机必须弄清每个对象的结构,如果关心性能,并且需要读写大量的特定类对象,就应该考虑使用Externalizable接口。
警告:不同于readObject和writeObject方法,他们是私有的并且只能被序列化机制调用,readExternal和writeExternal方法是公有的。特别是,readExternal方法潜在地运行对一个已经存在的对象状态进行修改。
12.5.6 单元素与类型安全枚举的序列化
12.5.7 版本
类可以指出自己兼容于其早期版本。为了实现这一点,首先必须获得该类的早期版本的指纹,可以使用一个独立的程序serialver,它是JDK的一部分来获得这个数值。
12.5.8 使用序列化进行克隆
序列化机制提供了一种很简单的方法来克隆一个对象,只要被提供的类是序列化的。
要克隆一个序列化的对象,只需要就爱你过对象序列化到输出流中,然后读回即可。其结果是一个新的对已存在对象进行了深度拷贝的对象。不需要将对象写入文件——可以使用一个ByteArrayOutputStream来存储数据到一个字节数组中。
12.6 文件管理
注意:就像Java中经常使用的方法那样,File类也仅仅有最少的公共操作方法。比如在Windows中,可以查询(或设置)文件的只读标志,但尽管可以查询一个文件是否隐藏,却不能将它设置为隐藏,除非使用本地方法。
提示:如果处理文件或者目录名,就应该使用File对象,而不是字符串。
警告:如果在Windows中构造File对象时,使用正斜杠作为目录分隔符,那么getAbsolutePath方法将但会一个包括正斜杠的文件名,Windows用户会感觉有点奇怪。实际上,应该使用geCanonicalPath方法。它将使用反斜杠代替正斜杠。
12.7 新的I/O
JDK4.0包含了一些改进输入、输出处理的新特性,它们包含在java.nio包中,被称为“新的I/O”。
此包支持下列特性:
内存映射文件
文件锁定
字符集编码和解码
非阻塞I/O
12.7.1
使用java.nio包建立内存映射很简单。下面是需要的步骤:
首先,为文件获取通道(channel)。通道时对于磁盘文件的抽象,允许访问操作系统的特性,如文件间的内存映射、文件锁定和快速数据传输。通过调用增加到FileInputStream、FileOutputStream和RandomAccessFile类中的getChannel方法就可以获得通道。
FileInputStream in=new FileInputStream(...);
FileChannel channel=in.getChannel();
通过调用FileChannel类的map方法可以获得MappedByteBuffer。可以指定需要进行映射的文件区域和映射模式。有三种模式:
FileChannel.MapMode.READ_ONLY:结果缓存区是只读的。任何试图写入缓存区的举动都将抛出ReadOnlyBufferException。
FileChannel.MapMode.READ_WRITE:结果缓存区可写,这些改变会及时写会文件中。注意,如果其他程序也映射了同一个文件,它并不会立即观察到这些变化。多个程序同时对同一文件进行映射的具体行为依赖于操作系统。
FileChannel.MapMode.PRIVATE:结果缓存区可写,但是任何改变都是私有的,仅仅对该缓存区有效,并不会写入文件中。
一旦获取了缓冲区,可以用ByteBuffer类和Buffer超类读写数据。
缓冲区支持顺序和随机数据访问。缓冲区有一个被get和put操作使用的位置。
12.7.2 缓存区数据结构
当使用内存映射时,制作了一个横跨整个文件的缓冲区,或者是文件中的一个感兴趣的区域。也可以使用缓冲区来读写更多的普通信息块。
一个缓冲区就是一个相同类型的值的数组。Buffer类是一个抽象类,它包含以下子类:ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer。在实际应用中,使用最多的是ByteBuffer和CharBuffer。
一个缓存区具有:
一个绝不会改变的容量(capacity)。
一个下一数值读取或写入的位置(position)。
一个限制(limit),超出这个限制的读写时无意义的。
可选地,一个重复进行读写操作的标志(mark)。
12.7.3 文件锁定
要锁住一个文件,调用FileChannel类的lock或tryLock方法:
File lock=channel.lock();
或者
File lock=channel.tryLock();
第一个调用一直处于阻塞状态直到该锁可用。第二个调用立刻返回,返回该锁或者是null(如果该锁不可用)。第一个文件保持封锁状态知道通道关闭,或者对锁调用release方法。
注意:如果锁住文件的尾部,而文件后来增加的内容超过了锁住的位置,则多出的部分并没有锁住。要锁住全部字节,使用大小为Long.MAX_VALUE。
记住文件锁是与系统相关的。要注意以下几点:
在一些系统中,文件锁仅仅是建议性的(advisory)。因此,如果一个应用程序未能获得锁,它也可以对文件进行读写操作,尽管其他应用程序已经锁住文件。
在一些系统中,不能同步地锁住一个文件并把它映射到内存中。
文件锁是整个Java虚拟机持有的。如果两个程序使用同一个虚拟机执行(例如,一个applet或者应用程序启动器),则它们不能对同一个文件获得锁。如果虚拟机已经拥有了对同一个文件的重叠锁,则lock或者truLock方法会抛出OverlappingFileLockException异常。
在某些系统上,关闭通道会释放Java虚拟机拥有的文件上全部的锁。因此应该避免对同一个被锁定的文件打开多个通道。
对网络文件系统中的文件锁定是和系统高度相关的,因此应该避免这么做。
12.8 正则表达式           
正则表达式是用来指定字符串模式的。任何时候只要需要定位一个匹配特定模式的字符串,都可以使用正则表达式。
分享到:
评论

相关推荐

    第12章输入输出流、文件及数据库操作.doc

    第12章输入输出流、文件及数据库操作.doc

    java面向对象程序设计课程每章ppt(共15章+复习1章).zip

    第12章 JDK8中的日期.pptx 第12章 字符串、日期.pptx 第13章 容器和泛型.pptx 第14章 流与文件(1).pptx 第14章 流与文件(2).pptx 第15章 网络编程.pptx 第1章 Java概述.pptx 第2章 Java基础.pptx 第3章 数组....

    第12章 文件操作-按字符读写文件1

    第12章 文件操作——按字符读写文件C语言程序设计第12章 文件操作按字符读写文件向标准输出流stdout(默认屏幕)写一个字符int getchar(void

    Linux与UNIX Shell编程指南.rar

    第十二章 TR用法 第三部分 登录环境 第十三章 登录环境 第十四章 环境和SHELL变量 第十五章 小结 第四部分 基础SHELL编程 第十六章 SHELL脚本介绍 第十七章 条件测试 第十八章 控制流结构 第十九章 SHELL函数 第二...

    13.第十三章 文件.txt

    第十三章 文件 对数据的管理无论是用数组还是链表,都是存储在内存中的,程序结束后都会丢失,下一次运行程序时,要重新输入或运算生成数据。要把程序运行的数据保存起来以便下次运行继续使用,在计算机中持久保存...

    Java2核心技术.part5

    第12章流与文件 12.1流 12.2完整的流结构 12.2.1流过滤器的分层 12.2.2数据流 12.2.3随机存取文件流 12.2.4文本流 12.2.5字符集 12.2.6文本输出 12.2.7文本输入 12.3 ZIP文件流 12.4流...

    Java2核心技术.part3

    第12章流与文件 12.1流 12.2完整的流结构 12.2.1流过滤器的分层 12.2.2数据流 12.2.3随机存取文件流 12.2.4文本流 12.2.5字符集 12.2.6文本输出 12.2.7文本输入 12.3 ZIP文件流 12.4流...

    Java2核心技术.part1

    第12章流与文件 12.1流 12.2完整的流结构 12.2.1流过滤器的分层 12.2.2数据流 12.2.3随机存取文件流 12.2.4文本流 12.2.5字符集 12.2.6文本输出 12.2.7文本输入 12.3 ZIP文件流 12.4流的使用 ...

    Java2核心技术.part6

    第12章流与文件 12.1流 12.2完整的流结构 12.2.1流过滤器的分层 12.2.2数据流 12.2.3随机存取文件流 12.2.4文本流 12.2.5字符集 12.2.6文本输出 12.2.7文本输入 12.3 ZIP文件流 12.4流...

    Java2核心技术.part4

    第12章流与文件 12.1流 12.2完整的流结构 12.2.1流过滤器的分层 12.2.2数据流 12.2.3随机存取文件流 12.2.4文本流 12.2.5字符集 12.2.6文本输出 12.2.7文本输入 12.3 ZIP文件流 12.4流...

    Java2核心技术.part2

    第12章流与文件 12.1流 12.2完整的流结构 12.2.1流过滤器的分层 12.2.2数据流 12.2.3随机存取文件流 12.2.4文本流 12.2.5字符集 12.2.6文本输出 12.2.7文本输入 12.3 ZIP文件流 12.4流...

    基于MATLAB的金融数据分析 金融MATLAB-第03章 MATLAB与Excel文件的数据交换(共41页).ppt

    基于MATLAB的金融数据分析 金融MATLAB-第12章 马克维兹均值 方差模型(共19页).ppt 基于MATLAB的金融数据分析 金融MATLAB-第13章 投资组合绩效(共22页).ppt 基于MATLAB的金融数据分析 金融MATLAB-第17章 固定收益...

    基于MATLAB的金融数据分析 金融MATLAB-第10章 期权定价模型与数值方法(共23页).ppt

    基于MATLAB的金融数据分析 金融MATLAB-第12章 马克维兹均值 方差模型(共19页).ppt 基于MATLAB的金融数据分析 金融MATLAB-第13章 投资组合绩效(共22页).ppt 基于MATLAB的金融数据分析 金融MATLAB-第17章 固定收益...

    基于MATLAB的金融数据分析 金融MATLAB-第05章 贷款按揭与保险产品 现金流分析案例(共44页).ppt

    基于MATLAB的金融数据分析 金融MATLAB-第12章 马克维兹均值 方差模型(共19页).ppt 基于MATLAB的金融数据分析 金融MATLAB-第13章 投资组合绩效(共22页).ppt 基于MATLAB的金融数据分析 金融MATLAB-第17章 固定收益...

    shell编程指南,shell脚本,本书共分五部分全。grep家族,sed,AWK,正则表达式,tr用法

    第12章 tr用法 119 第三部分 登录环境 第13章 登录环境 125 第14章 环境和shell变量 132 第15章 引号 146 第四部分 基础shell编程 第16章 shell脚本介绍 151 第17章 条件测试 154 第18章 控制流结构 160 第19章 ...

    TCPIP协议详解卷一

    第十二章 多播与广播 第十三章 IGMP 第十四章 DNS 第十五章 TFTP:简单文件传送协议 第十六章 BOOTP: 引导程序协议 第十七章 TCP: 传输控制协议 第十八章 TCP连接的建立与终止 第十九章 TCP的交互数据流 第二十章 TCP...

    精通MATLAB—综合辅导与指南

    第12章 三次条样 第13章 数值分析 第14章 富里哀分析 第15章 低级文件I/O 第16章 调试工具 第17章 二维图形 第18章 三维图 第19章 颜色 第20章 句柄图 第21章 创建图形用户界面 文件 21.11 小结 第22章 符号数学...

    Linux命令学习 shell pdf格式

    第十二章 tr用法 第三部分 登录环境 第十三章 登录环境 第十四章 环境和shell变量 第十五章 引号 第四部分 基础shell编程 第十六章 shell脚本介绍 第十七章 条件测试 第十八章 控制流结构 第十九章 shell函数 第二...

    fluent 6.23 教程01 序言

    第十二章、污染形成模型 第十三章、相变模拟 第十四章、多相流模型 第十五章、动坐标系下的流动 第十六章、解算器的使用 第十七章、网格适应 第十八章、数据显示与报告界面的产生 第十九章、图形与可视化 第二十章、...

Global site tag (gtag.js) - Google Analytics