12 第十二章 高级IO流Word文档下载推荐.docx
《12 第十二章 高级IO流Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《12 第十二章 高级IO流Word文档下载推荐.docx(15页珍藏版)》请在冰豆网上搜索。
voidclose()你完成流操作之后,就关闭这个流。
如果你有一个流所组成的栈,使用过滤器流,就关闭栈顶部的流。
这个关闭操作会关闭其余的流。
intavailable()
这个方法报告立刻可以从流中读取的字节数。
在这个调用之后的实际读操作可能返回更多的字节数。
skip(long)这个方法丢弃了流中指定数目的字符。
booleanmarkSupported()
voidmark(int)
voidreset()
如果流支持"
回放"
操作,则这些方法可以用来完成这个操作。
如果mark()和reset()方法可以在特定的流上操作,则markSupported()方法将返回ture。
mark(int)方法用来指明应当标记流的当前点和分配一个足够大的缓冲区,它最少可以容纳参数所指定数量的字节。
在随后的read()操作完成之后,调用reset()方法来返回你标记的输入点。
OutputStream
voidwrite(int)
voidwrite(byte[])
voidwrite(byte[],int,int)
这些方法写输出流。
和输入一样,总是尝试以实际最大的块进行写操作。
voidclose()当你完成写操作后,就关闭输出流。
如果你有一个流所组成的栈,就关闭栈顶部的流。
voidflush()
有时一个输出流在积累了若干次之后才进行真正的写操作。
flush()方法允许你强制执行写操作。
字符流
Reader
intread()
intread(char[])
intread(char[],intoffset,intlength)
简单读方法返回一个int值,它包含从流里读出的一个字符或者-1,其中-1表明文件结束。
其它两种方法将数据读入到字符数组中,并返回所读的字符数。
第三个方法中的两个int参数指定了所要填入的数组的子范围。
voidclose()
booleanready()
voidskip(long)
这些方法与InputStream中的对应方法相似
Writer
voidwrite(intc)
voidwrite(char[])
voidwrite(char[],intoffset,intlength)
voidwrite(Stringstring)
voidwrite(Stringstring,intoffset,intlength)
所有这些方法与OutputStream中的方法类似。
节点流
Java2SDK中有三种基本类型的节点:
文件(file)、内存(memory)、管道(pipe)。
如
过程流
过程流在其它流之上,完成排序、变换等操作。
过程流也被称做过滤流。
当你需要改变输入流的原始数据时,你可以将一个过滤输入流连接到一个原始的输入流上。
用过滤流将原始数据变换成你需要的格式。
其分类如图
基本字节流类
分类如图
FileInputStream和FileOutputStream
这两个节点流用来操纵磁盘文件。
这些类的构造函数允许你指定它们所连接的文件。
要构造一个FileInputStream,所关联的文件必须存在而且是可读的。
如果你要构造一个FileOutputStream而输出文件已经存在,则它将被覆盖。
主要用于操作二进制或者带有格式的文件:
如压缩文件,可执行文件等。
FileInputStreaminfile=newFileInputStream("
myfile.dat"
);
FileOutputStreamoutfile=newFileOutputStream("
results.dat"
BufferInputStream和BufferOutputStream
带有缓冲区的流,BufferInputStream一次可以读入一定长度的数据(默认2048字节),BufferOutputStream一次可以一定长度的数据(默认512字节),可以提高I/O操作的效率。
需要和其它的流类配合使用。
BufferOutputStream在使用时,为了确保把数据写出去,建议最后执行flush()将缓冲区中的数据全部写出去。
PipedInputStream和PipedOutputStream
管道流用来在线程间进行通信。
一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。
要使管道流有用,必须有一个输入方和一个输出方。
DataInputStream和DataOutputStream
用来对java的基本数据类型读写的类
DataInputStream方法
bytereadByte()
longreadLong()
doublereadDouble()
StringreadUTF(DataInputin)
DataOutputStream方法
voidwriteByte(byte)
voidwriteLong(long)
voidwriteDouble(double)
voidwriteUTF(Stringstr)
PrintStream
可以自动进行字符转换的动作,默认会使用操作系统的编码处理对应的字符。
importjava.io.*;
publicclassPrintStreamDemo{
publicstaticvoidmain(String[]args)throwsFileNotFoundException{
PrintStreamout=newPrintStream(newFileOutPutStream("
1.txt"
));
out.println
(1);
out.close();
}
}
基本字符流类
阐述了Reader和Writer字符流的体系结构。
InputStreamReader和OutputStreamWriter
用于字节流与字符流之间的转换接口。
当你构造一个InputStreamReader或OutputStreamWriter时,转换规则定义了16位Unicode和其它平台的特定表示之间的转换。
InputStreamReader从一个数据源读取字节,并自动将其转换成Unicode字符。
如果你特别声明,InputStreamReade会将字节流转换成其它种类的字符流。
OutputStreamWriter将字符的Unicode编码写到输出流,如果你的使用的不是Unicode字符,OutputStreamWriter会将你的字符编码转换成Unicode编码。
BufferedReader和BufferedWriter
因为在各种格式之间进行转换和其它I/O操作很类似,所以在处理大块数据时效率最高。
在InputStreamReader和OutputStreamWriter的结尾链接一个BufferedReader和BufferedWriter是一个好主意。
记住对BufferedWriter使用flush()方法。
FileReader和FileWriter
以字符的方式操作文件的类,主要用于操作文本文件。
PrintWriter
与PrintStream相类似,使用println()输出内容。
URL输入流
除了基本的文件访问之外,Java技术提供了使用统一资源定位器(URL)来访问网络上的文件。
当你使用Applet的getDocumentBase()方法来访问声音和图象时,你已经隐含地使用了URL对象。
StringimageFile=newString("
images/Duke/T1.gif"
images[0]=getImage(getDocumentBase(),imageFile);
当然,你也可以直接使用URL如下:
.URLimageSource;
try{
imageSource=newURL("
}catch(MalformedURLExceptione){}
images[0]=getImage(imageSource,"
Duke/T1.gif"
使用RandomAccessFile随机访问文件
你经常会发现你只想读取文件的一部分数据,而不需要从头至尾读取整个文件。
你可能想访问一个作为数据库的文本文件,此时你会移动到某一条记录并读取它的数据,接着移动到另一个记录,然后再到其他记录――每一条记录都位于文件的不同部分。
Java编程语言提供了一个RandomAccessFile类来处理这种类型的输入输出。
创建一个随机访问文件
你可以用如下两种方法来打开一个随机存取文件:
用文件名
myRAFile=newRandomAccessFile(Stringname,Stringmode);
用文件对象
myRAFile=newRandomAccessFile(Filefile,Stringmode);
mode参数决定了你对这个文件的存取是只读(r)还是读/写(rw)。
例如,你可以打开一个数据库文件并准备更新:
RandomAccessFilemyRAFile;
myRAFile=newRandomAccessFile("
db/stock.dbf"
"
rw"
存取信息
RandomAccessFile对象按照与数据输入输出对象相同的方式来读写信息。
你可以访问在DataInputStrem和DataOutputStream中所有的read()和write()操作。
Java编程语言提供了若干种方法,用来帮助你在文件中移动。
longgetFilePointer();
返回文件指针的当前位置。
voidseek(longpos);
设置文件指针到给定的绝对位置。
这个位置是按照从文件开始的字节偏移量给出的。
位置0标志文件的开始。
longlength()返回文件的长度。
位置length()标志文件的结束。
添加信息
你可以使用随机存取文件来得到文件输出的添加模式。
java.log"
myRAFile.seek(myRAFile.length());
对象串行化
java.io.Serializable接口支持将一个Java技术对象存放到一个流中。
将一个对象存放到某种类型的永久存储器上称为"
保持"
。
如果一个对象可以被存放到磁盘或磁带上,或者可以发送到另外一台机器并存放到存储器或磁
盘上,那么这个对象就被称为可保持的。
java.io.Serializable接口没有任何方法,它只作为一个"
标记"
,用来表明实现了这个接口的类可以串行化。
类中没有实现Serializable接口的对象不能被保持。
当一个对象被串行化时,只有对象的数据被保存;
方法和构造函数不属于串行化流。
如果一个数据变量是一个对象引用,那么这个对象的数据成员也会被串行化。
树或者对象数据的结构,包括这些子对象,构成了对象图。
因为有些对象类所表示的数据在不断地改变,所以它们不会被串行化;
例如,java.io.FileInputStream、java.io.FileOutputStream和java.lang.Thread等流。
如果一个可串行化对象包含某个不可串行化元素的引用,那么整个串行化操作就会失败,而且会抛出一个NotSerializableException。
如果对象图包含一个不可串行化的引用,只要这个引用已经用transient关键字进行了标记,那么对象仍然可以被串行化。
publicclassMyClassimplementsSerializable{
publictransientThreadmyThread;
privateStringcustomerID;
privateinttotal;
域存取修饰符对于被串行化的对象没有任何作用。
写入到流的数据是字节格式,而且字符串被表示为UTF(文件系统安全的通用字符集转换格式)。
transient关键字防止对象被串行化。
privatetransientStringcustomerID;
实例分析
例1:
从第一个命令行参数代表的文件中读字符,然后写入第二个参数代表的文件。
问题分析
本题中需要从文件读,写数据,需要使用到与文件有关的流FileReader/FileWriter。
可以通过运行时参数提供文件的名称。
使用带有Buffer功能的流
为了提高读写数据的效率,可以使用带有buffer功能的流完成文件读写,并且可以以行为单位读写数据。
使用类BufferedReader,BufferedWriter
I/O流的链
在程序中很少使用单独一个流对象,实际做法是将几个流对象串联起来处共同理数据。
这样做会提高程序的效率。
数据源->
FileInputStream->
BufferedInputStream->
DataInputStream->
程序
数据源<
-DataOutputStream<
-BufferedOutputStream<
-FileOutputStream<
-程序
编写代码
publicclassTestBufferedStreams{
publicstaticvoidmain(String[]args){
try{
FileReaderinput=newFileReader(args[0]);
BufferedReaderbufInput=newBufferedReader(input);
FileWriteroutput=newFileWriter(args[1]);
BufferedWriterbufOutput=newBufferedWriter(output);
Stringline=bufInput.readLine();
while(line!
=null){
bufOutput.write(line,0,line.length());
bufOutput.newLine();
line=bufInput.readLine();
}
bufInput.close();
bufOutput.close();
}catch(IOExceptione){
e.printStackTrace();
}
编译运行
javacTestBufferedStreams.java
javaTestBufferedStreamsuser.batuserbak.bat
例2:
使用管道流完成线程之间的通讯。
1问题分析
本题中需要一个线程向管道写入数据,另外一个线程从管道中读出数据,需要使用到与管道有关的流PipedInputStream和PipedOutputStream。
2使用管道流
PipedInputStreamin=newPipedInputStream();
PipedOutputStreamout=newPipedOutputStream(in);
3编写代码
publicclassTestPipeStream{
PipedInputStreamin1=newPipedInputStream();
PipedOutputStreamout1=newPipedOutputStream(in1);
PipedInputStreamin2=newPipedInputStream();
PipedOutputStreamout2=newPipedOutputStream(in2);
ThreadCtc=newThreadC(out1);
ThreadZtz=newThreadZ(out2,in1);
ThreadQtq=newThreadQ(in2);
tc.start();
tz.start();
tq.start();
}catch(Exceptione){
staticclassThreadCextendsThread{
DataOutputStreamdos=null;
publicThreadC(OutputStreamos){
dos=newDataOutputStream(os);
publicvoidrun(){
while(true){
try{
doubled=Math.random();
dos.writeDouble(d);
sleep
(2);
}catch(Exceptione){
e.printStackTrace();
}
};
staticclassThreadZextendsThread{
DataInputStreamdis=null;
publicThreadZ(OutputStreamos,InputStreamis){
dis=newDataInputStream(is);
doubled=dis.readDouble();
staticclassThreadQextendsThread{
publicThreadQ(InputStreamis){
System.out.println(d);
编译运行
javacTestPipeStream.java
javaTestPipeStream
例3:
保存所有的Person对象到文件并以对象的方式读出来
本题中需要对文件读,写对象数据,需要使用到与对象有关的流ObjectInputStream/ObjectOutputStream。
2使用对象的读写流
ObjectOutputStream用于将一个对象输出,输出对象使用的方法为writeObject(Objectobj)
ObjectInputStream用于读取一个对象,读取对象使用的方法为readObject()
注意:
被读写的对象必须是已序列化的类的对象,即要实现要Serializable接口。
importjava.util.*;
classPersonimplementsSerializable{
Stringname=null;
publicPerson(Strings){
name=s;
publicStringtoString(){
returnname;
publicclassTestObjectStream{
ObjectOutputStreamoos=null;
ObjectInputStreamois=null;
Filef