黑马程序员-Java基础总结11——IO流(二)

时间:2021-08-05 12:03:32
黑马程序员-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流: PipedInputStreamPipedOutputStream 
 
注: 在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。