黑马程序员-Java基础总结11——IO流(二)
------- android培训、java培训、期待与您交流! ----------
内容:
打印流(PrintStream与PrintWriter)、序列流(合并流/SequenceInputStream)、
对象流(ObjectInputStream与ObjectOutputStream)、
管道流(PipedInputStream与PipedOutputStream)、
RandomAccessFile(直接操作文件类)、数据流与字符编码
———————————————IO流中的其他流——————————————
十、IO流中的其他流:
1、打印流:
该流提供了打印方法,可以将各种数据类型的数据都原样打印。 打印流PrintStream、PrintWriter,可使用print类的打印方法(print、printf、println等),这两个流都是能直接操作文件的IO流。(它们属于装饰类,可为其他流提供这些打印功能)。
PrintStream : 可直接写入字符串,然后将这些数据以字节流形式输出流或存储到文件中;
PrintWriter : 直接写入字符串数据,将数据以字符流形式输出。
PS:
printf : 打印带格式的语句
2、序列流(合并流):
SequenceInputStream ; 将多个流合并成一个流(即提取多个流中数据合并到一个流);
序列流构造函数使用参数:
InputStream : 直接传入输入流,不过只能传入两个。
Enumeration<? extends InputStream> : 枚举(List集合中Vector的特有功能)
(如果要合并两个以上的流就需要使用 带枚举的构造函数) 注意: 由于Vector效率较低,而SequenceInputStream接收的也只是实现枚举的实例化对象,因此可通过(带名字的)匿名内部类(实现Enumeration接口),并结合ArrayList及迭代器(iterator)存储输出数据到枚举方法中。
【实现格式: 】
ArrayList<InputStream> al = new ArrayList<InputStream>();
final Iterator it = al.iterator(); (因为匿名内部类访问的外部类中的 局部变量 必须是被 final 所修饰的)
3、切割文件:
(这不是一个流,而是一种实现方式,即可操作的功能) 思路:
1、定义一个数据存储容器(指定数据存储大小);
2、定义计数器(计数读写次数,可便于大文件分割的使用,因为数据操作内存有限);
3、读写一定数据后(满足计数器的定量后),关闭输出流,开启新的存储数据的流以及文件,直到可操作数据结束。
由于读取写入数据时使用的时系统内存,而操作数据的临时内存通常为64MB,所以可以定义多个数据容器,每次提取一部分数据输出到流中(进行计数),但满足一定次数时可以关闭流对象,开启新的流对象进行存储(即可实现切割文件的操作)
——————————————对象流——————————————
十一、对象流:
ObjectInputStream 与 ObjectOutputStream ;
从文件中读取对象的属性信息或存储对象的属性信息到文件中 的流。 代码示例:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.Object"));
Person p = (Person)ois.readObject();
可被操作的类对象(Person)的基本需要:
对象的序列化:
(存储文件的后缀名一般为.Object格式。) 1、实现java.io.Serializable接口(这是一个标志接口,即没有可操作方法的接口);
2、使用默认或自定义UID序列号,用于给jvm虚拟机标识(知道该文件是序列化类);
3、当源文件类属性发生改变(增删属性或修饰符等)时,该文件的序列化也将发生改变;
(因为该UID号是根据类中成员属性计算得出的) 4、要使旧的文件还能和修改后的匹配数据,最好是自定义UID序列化。
自定义UID序列号:
public static final long serialVersionUID = 42L; (等)
注意:
静态static修饰的类变量(属性),不能被序列化;【属于静态区,非堆内存中数据】
被transient修饰的类变量也不能被序列化。
【transient修饰变量只在堆内存中存在而不能存储到文本文件中】 因为序列化是将堆内存中的类的变量存储到文本文件中(transient修饰的变量不可序列化)。
1、Object流方法:
writeObject()
: 写入一个对象的属性到文件中; (注意: 在结束对象的写入后要在末尾添加写入"null"这个对象,作为结束标识)
readObject() :
每次读取文件中的一个对象(但是是带标识的,所以迭代提取)。 (有null结束标识才能在读取到文件结尾处判断是否null,否则会抛出EOFException异常)
2、输出文件只能是复写,不能在文件末尾追加,否则抛出StreamCorruptedException
异常。
——————————————管道流—————————————————
十二、管道流:
PipedInputStream 与 PipedOutputStream
涉及多线程的IO流: PipedInputStream、PipedOutputStream
注: 在IO流中既可以输入流读取数据、然后由输出流输出;(IO流中绝大部分流是这样)
也可以写入数据到输出流中,然后传递到输入流缓冲区,由其读出数据后进行操作。
(管道流就是后者这种功能,主要用于Java组件间的数据传递)
连接管道流代码:
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
: 将读取流连接到对应的输出流。 【在不同线程(run方法中)执行对管道输出流写入数据或从管道输入流读取数据】
管道流应用:
可实现在A组件(例:GUI的对话框)输入数据,由管道输出流输出该数据,传递给B组件中管道读取流,然后在B组件中对数据进行处理或打印等。 扩展性:
输出流,可接收不同源的数据(文件或键盘录入到指定文本框); 读取流,可根据需要输出不同格式的数据或其他处理功能。
管道流方法:
write(byte[] b, int off,int len)
: 输出流写入数据方法; read(
byte[] b, int off,int len
);: 读取流读取数据方法,是阻塞式方法(在没获取到数据时会等待直到有数据输入,所以管道流的读取、输出必须是存在于多线程,两者要分开,不然会死锁。)
——————————————RandomAccessFile——————————————
十三、RandomAccessFile:
RandomAccessFile直接继承自Object类,可直接操作文件,且读取、写入均可执行。
(此流,既能读取文件也能写入数据到文件中,因为其内部实现了DataInput和DataOutput接口(DataInputStream和DataOutputStream也各自实现该接口),没有使用InputStream和OutputStream提供的功能,完全独立的类,不属于IO流的子类)
构造函数:
RandomAccessFile(File file,String mode)等
:
创建从中读取和向其中写入(可选: 通过指定mode的数值)的随机访问文件流; mode操作文件模式:
"r" (只读) 、 "rw"(读写); 还有 "rws"和"rwd"(是基于"rw",但要求不同程度的更新数据到底层存储设备。)
功能: 随机读取/写入数据到文件(只能操作文件),因为该流存在文件指针(类似byte[]数组),可通过调整文件指针(可向前、向后)或跳过指定字节数(只能向后)来随机访问(读写)数据。
应用: 因为可通过调整文件指针控制数据的读取/写入位置,所以可结合多线程使用,分段读取、写入(例:分段下载程序)文件,实现多线程同时操作文件功能。(重点应用功能)
方法:
(详见java.io.RandomAccessFile类)
readInt(); : 读取一个4字节的整数;
writeInt(); : 写入一个4字节的整数;
……………………………………………
seek(long pos) : 控制文件指针的位置;
skipBytes(int n) : 读取数据时跳过指定数量的字节(跳过只能向后);
———————————数据流与字符编码———————————————
十四、操作数据流与字符编码:
1、操作基本数据类型的流:
DataInputStream、DataOutputStream ; 2、内存中操作数据的流 :
(没有调用底层资源,关闭流无效) A、字节数组流 : ByteArrayInputStream、ByteArrayOutputStream;
B、字符数组流:CharArrayReader、CharArrayWriter;
C、字符串流:StringReader、StringWriter;
字符编码:
ASCII
: 美国标准信息交换代码(拉丁字母编码); GBK
: 汉语编码,汉字占两字节; UTF-8
: 万国码,汉字占三字节; UTF-8修正
: 万国码修正版,汉字占四字节; ISO8859-1
: 欧洲字母编码表,同ASCII无汉字等字符; 【PS: 中文系统默认编码: GBK,网址(Tomcat)服务器默认编码: ISO8859-1。】
知识点小统计:
装饰流:
缓冲流(BufferedStream,例: LineNumberReader等)、操作基本数据流(DataInputStream/DataOutputStream); 直接操作文件的流: 打印流(PrintStream、PrintWriter)、File类流等;
结合多线程使用的IO流: 管道流(至少两个线程读取、写入)、RandomAccessFile。