IO流之其他功能类详解Word文档格式.docx
《IO流之其他功能类详解Word文档格式.docx》由会员分享,可在线阅读,更多相关《IO流之其他功能类详解Word文档格式.docx(21页珍藏版)》请在冰点文库上搜索。
![IO流之其他功能类详解Word文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/9/ab0f7b2f-f104-40ab-bfc8-f21a7c0d3aff/ab0f7b2f-f104-40ab-bfc8-f21a7c0d3aff1.gif)
while((line=br.readLine())!
=null)
{
if("
over"
.equals(line))
{
break;
}
pw.println(line.toUpperCase());
//
//pw.flush();
}
br.close();
pw.close();
}
合并流(SequenceInputStream)
我们首先将一个mp3文件切割成一个个碎片,这里就涉及到IO流的应用,我们把切割代码演示如下:
classSpilteDemo
spite();
publicstaticvoidspite()throwsIOException
FileInputStreamfis=newFileInputStream("
1.mp3"
);
FileOutputStreamfos=null;
byte[]buf=newbyte[1024*1024];
intlen=0;
intcount=1;
while((len=fis.read(buf))!
=-1){
//每次循环我们都创建一个写入流,保存到递增的文件中
fos=newFileOutputStream("
c:
//splitest//"
+(count++)+"
.part"
fos.write(buf,0,len);
fos.close();
fis.close();
然而我们有时需要将文件合并到一起,那么我们怎么办呢?
我们这时就需要一个IO流的合并流
合并流(SequenceInputStream)即将多个流合并成一个流,即多个文件合并成一个文件
构造方法:
SequenceInputStream(Enumeration<
?
extendsInputStream>
e):
接收一个Enumeration类型参数,需要用到集合
我们通过代码简单演示下如何将之前MP3文件合并在一起:
importjava.util.*;
classSequenceInputStreamDemo
//只有Vector才有Enumeration
Vector<
FileInputStream>
v=newVector<
();
v.add(newFileInputStream("
//splitest//1.part"
));
//splitest//2.part"
//splitest//3.part"
//splitest//4.part"
//splitest//5.part"
//splitest//6.part"
//splitest//7.part"
//splitest//8.part"
Enumeration<
e=v.elements();
//创建一个合并流,且构造方法传入的必须是Enumeration类型
SequenceInputStreamsis=newSequenceInputStream(e);
//将多个文件的数据传入到4.txt
BufferedOutputStreambw=
newBufferedOutputStream(newFileOutputStream("
//mp3//1.mp3"
while((len=sis.read())!
bw.write(len);
sis.close();
bw.close();
对象流(对象序列化ObjectStream)
对象流是可以将对象以序列化的方式存入到一个文件里,对象流有非常重要的两个类,该两个类是成对出现的。
ObjectOutputStream:
将对象存储到一个文件中
存储方法:
voidwriteObject(Objectobj)
ObjectInputStream:
操作输出对象流一保存的数据,通常和ObjectOutputStream成对使用。
读取方法:
voidreadObject();
我们基本演示下将Person对象存入到文件中:
classObjectDemo
publicstaticvoidmain(String[]args)throwsException
writeObj();
//要先写再读
readObj();
publicstaticvoidreadObj()throwsException
ObjectInputStreamois=newObjectInputStream(newFileInputStream("
object.txt"
Personp=(Person)ois.readObject();
System.out.println(p);
ois.close();
publicstaticvoidwriteObj()throwsIOException
ObjectOutputStreamoos=newObjectOutputStream(newFileOutputStream("
oos.writeObject(newPerson("
zhangsan"
13));
oos.close();
classPersonimplementsSerializable//必须要实现这个接口,是对象序列化
Stringname;
intage;
Person(Stringname,intage)
this.age=age;
this.name=name;
publicStringtoString()
returnname+"
:
"
+age;
注意:
a)当我们该掉Person任何一个成员属性时,再读取就会出错,是因为java内部有个叫UID的长整型的编号将Person中的属性编号,无论改变成员变量值还访问权限,都会报错,读取失败,如果想改变而又不读取失败,可以加上这段代码:
ANY-ACCESS-MODIFIERstaticfinallongserialVersionUID=42L;
红色的是任何访问修饰符。
、
b)我们想存储的对象的类必须要实现一个接口Serializable,是其对象序列化
c)要存储的对象类中成员属性不能是static修饰的,这样无法序列化,当然我们想让成员变量无法序列化也可在其加上transient
管道流(PipedStream)
管道流是IO中一个非常特殊的流,他是和多线程联系在一起的。
管道流输入输出是连接在一起的。
输入流:
PipedInputStream
输出流:
PipedOutputStream
管道流的输入输出连接是通过两种方法实现:
a)构造一个无参数的构造方法,使用connect()方法去连接输入和输出
b)构造一个有参数的构造方法,传入的是自己的输入或者输出流
我们基本演示下管道流的应用:
classReadimplementsRunnable
PipedInputStreampis;
Read(PipedInputStreampis){
this.pis=pis;
publicvoidrun()
try
byte[]buf=newbyte[1024];
System.out.println("
没有数据,线程没有阻塞"
intlen=pis.read(buf);
System.out.println("
读取数据中。
。
阻塞结束"
Stringstr=newString(buf,0,len);
System.out.println(str);
//打印读取到的数据
pis.close();
catch(Exceptione)
thrownewRuntimeException("
管道流输入失败"
classWriteimplementsRunnable
PipedOutputStreampos;
Write(PipedOutputStreampos){
this.pos=pos;
try{
开始写入数据,等待6秒后"
Thread.sleep(6000);
pos.write("
haha,pioediscome"
.getBytes());
pos.close();
}catch(Exceptione){
管道流输出失败"
classPipedIODemo
PipedInputStreampis=newPipedInputStream();
PipedOutputStreampos=newPipedOutputStream();
pis.connect(pos);
//连接输入和输出
newThread(newRead(pis)).start();
//开启读取线程
newThread(newWrite(pos)).start();
//开启写入线程
随机访问流(RandomAccessFile)
该类是随机访问文件的一个类,该类不能算是IO体系中子类,而是直接继承自Object,但是它是IO包中的成员,因为他具备读和写功能。
其内部封装了一个byte数组,对字节输出输入进行封装。
通过索引的方式对数组中的元素进行操作。
通过指针对数组的元素进行操作。
我们可以通过getFIlePointer获取指针位置。
同时可以通过seek改变指针的位置。
局限性:
只对文件操作。
随机访问的原理:
就是通过操作索引的方法对指针进行自定义的指定位置来进行读写
其实完成读写的原理就是内部封装了字节输入流和输出流。
但它有一个局限性就是通过构造方法可以看出,该类只能操作文件,而且操作文件还有模式。
模式:
a)r:
以只读方式打开
b)rw:
打开以便读取和写入
c)rws:
d)rwd:
如果模式为只读r,不会创建文件,会去读取一个已存在文件,如果该文件不存在,则会出现文件找不到(FileNotFoundException)异常。
如果模式为rw,操作的文件不存在,会自动创建,如果存在,不会覆盖。
而且该对象的构造函数要操作的文件不存在,会自动创建。
如果存在,不会覆盖。
我们基本演示下该类的用法:
classRandomAccessFileDemo
writeFile_2();
//readFile();
publicstaticvoidreadFile()throwsIOException
RandomAccessFileraf=newRandomAccessFile("
ran.txt"
"
r"
byte[]buf=newbyte[4];
//调整对象中的指针
//raf.seek(8);
//跳过指定的字节数
raf.skipBytes(8);
raf.read(buf);
Stringname=newString(buf);
System.out.println("
name:
+name);
intage=raf.readInt();
age:
+age);
publicstaticvoidwriteFile()throwsIOException
rw"
raf.write("
张三"
//写入Int类型,以免超出无法保存,一般开发够用了
raf.writeInt(97);
王五"
raf.writeInt(99);
raf.close();
/*
写入文件数据的随机性
*/
publicstaticvoidwriteFile_2()throwsIOException
//可以随机控制要写入的字节位置
raf.seek(8*0);
周期"
raf.writeInt(101);
总结:
该类三种特殊的地方:
首先它有有一个模式控制文件的读写操作,然后它有一个seek方法控制写入字节的位置,最后他的写入读取有多种基本类型,我们常用的是writeInt方法。
该类经常用在文件的下载,我们要重点掌握。
基本数据类型流(DataStream)
其用于操作基本数据类型的流
输入流:
DataInputStream
输出流
DataOutputStream
我们通过代码演示,基本的了解下DataStream的用法:
classDataStreamDemo
//writeData();
readData();
publicstaticvoidwriteData()throwsIOException
DataOutputStreamdos=newDataOutputStream(newFileOutputStream("
data.txt"
//我们按照什么顺序写入什么基本类型数据
dos.writeInt(289);
dos.writeBoolean(true);
dos.writeDouble(988.26);
dos.close();
publicstaticvoidreadData()throwsIOException
DataInputStreamdis=newDataInputStream(newFileInputStream("
//我们就按照什么顺序读取什么基本类型。
必须按顺序,否则取出来乱码
intnum=dis.readInt();
Booleanb=dis.readBoolean();
Doubled=dis.readDouble();
System.out.println(num);
System.out.println(b);
System.out.println(d);
注意这两个类个分别有特殊的方法是专门用来输入和读取UTF的方法,我们只能对应的去取文件的数据。
这两个方法分别是readUTF(),writeUTF()。
我们演示下这两个方法的用法:
//writeUTFData();
readUTFData();
publicstaticvoidwriteUTFData()throwsIOException
utfdata.txt"
dos.writeUTF("
你好"
//writeUTF只能解析中文
publicstaticvoidreadUTFData()throwsIOException
Strings=dis.readUTF();
System.out.println(s);
}
基本数据类型数组流(ByteArrayStream)
ByteArrayStream是用来操作字节数组的流对象,是写入到内存的特殊的流
ByteArrayInputStream:
在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayInputStream(byte[]buf)
ByteArrayOutputStream:
在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这就是数据目的地、
ByteArrayOutputStream()
常用的方法:
a)intsize:
返回缓冲区的当前数组大小
b)StringtoString:
将缓冲区内容转换为字符串
c)voidwriteTo(OutputStreamout):
将byte数组全部内容存到指定输入流文件中,这段代码需要抛IOException。
因为是两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭,且没有涉及到文件或者键盘等操作,所以不用抛IOException。
这个类就是用流的读写思想操作数组
我们来通过代码基本演示下这个流:
classArrayStreamDemo
publicstaticvoidmain(String[]args)
//数据源
ByteArrayInputStreambais=newByteArrayInputStream("
ABCDEFG"
//数据目的
ByteArrayOutputStreambaos=newByteArrayOutputStream();
inta=0;
while((a=bais.read())!
=-1)
baos.write(a);
System.out.println(baos.size());
//缓冲区的大小
System.out.println(baos.toString());
//唯一取出数组的方法
我们不仅有操作字节数组的,还有其他的基本类型数组操作,他们基本用法是一致的:
操作字符数组
CharArrayReader与CharArrayWrite
操作字符串
StringReader与StringWriter
字符编码
我们常用的编码表是UTF—8和GBK,UTF—-8是国际码表,一个汉字占三个字节,GBk是中国的码表,一个汉字占两个字节。
字节转换字符只能用IO流两个类
a)InputStreamReader和outputStrea