IO笔记
流:一组有序的字节集合,是数据在两个设备的传输个设备的传输
流的本质是数据传输,按照处理数据类型的不同,分为字节流 字符流
字节流以字节为单位,8bit ,包含两个抽象类 InputString OutoutString
字符流以字符为单位,根据码表映射字符,16bit,包含两个抽象类 Reader Writer
(Unicode 中每个字符都使用了多个字节,所以字节流不适用于处理此类信息)
字符流在处理数据输入输出时会用到缓存
基本字节流:
InputString
包含一个抽象方法 abstruct int read() 用于读取一个字节 并返回,在遇到结尾时返回-1;
类中其他非抽象方法都需要调用read(),所以子类只需要覆盖这一个抽象方法
abstruct int read();
int read (byte [] arr);//读入一个字节数组,并返回实际读取的数组长度,最大读取arr.length;碰到结尾时返回-1;
int read (byte [] arr, int off,int len );碰到结尾时返回-1;
long skip(long n);//跳过n个字节
int available();//返回在不阻塞的情况下,可读取的字节数
void close();//关闭输入流;在完成对流的读写时,应该调用这个方法,释放掉有限的系统操作资源,
viod mark();//标记下一个读取位置
void reset();
OutputString
包含一个抽象方法 abstruct int write(int b) 用于在某一个输出位置写入一个字节
abstruct int write(int n);
int write(byte[] arr);
int write (byte [] arr,int off ,int len);
void close();
void flush();//强制将缓冲区剩余的数据发往目的地
point: InputString,OutoutString,Reader,Writer都实现了Closeable接口,而OutputString和Writer还实现了Flushable接口
只有Writer实现了Appendable接口,可以调用append(char c);append(char charsequence s);用来添加单个字符和字符序列
FileInputString,FileOutputString(如果指定文件不存在,则创建一个新文件)
提供了一个附着在磁盘文件上的输入流和输出流,只需要在参数上提供文件名或者路径名即可
point:绝对路径:计算机中文件的存储位置 相对路径:Java中以工作目录开始
通过组合流实现具体任务的实现:若希望实现预先浏览下一个字节并读取数据也能够使用带缓冲机制的read()方法
DataInputStream dataInputStream= new DataInputStream(new PushbackInputStream(new BufferedInputStream(new FileInputStream("")) ));
FileInputString
FileInputStream (String name);
FileInputStream(File file );
FileOutputString
FileOutputString(String name ,boolean append);
FileOutputString(File file);
FileOutputString(File file ,boolean append);//若append==true,则当前文件可追加,并且重名文件不会被删除
基本字符流:Reader/Writer 实现对不同平台之间数据流中数据进行转换的功能
Java使用Unicode字符集来表示字符和字符串,需要用两个字节十六位来表示一个字符,不同于使用一个字节8位表示一个字符的ASCII字符集。
Reader 中实现的方法有:
void close();
void mark();
Boolean markSupported();
int read();
int read (char [ ] chars);
int read (char [ ] chars ,int off ,int len);
boolean ready();
void reset();
long skip(long n);
Writer 中实现的方法:
void close();
void flush();
void write(char chars);
void write(char [ ] chars ,int off ,int len);
void write(int c);
void write(String str);
void write (String str,int off ,int len);
转换流:InputSringReader/OutputStringWriter
用于转换字节流与字符流;在构造方法中通过制定一定的平台规范,把以字节表示的流转换为特定平台上的字符表示,
InputStringReader(InputString in);
InputStringReader(InputString in, String enc);//制定规范enc
OutputStringWriter(OutputString out);
OutputStringWriter(OutputString out, String enc);
缓冲区数据流:
BufferedInputStream/BuffereOutputStream//创建一个带缓冲区的输入输出流,数据以块为单位先进入缓冲区,其后的读写操作均在缓冲区上进行,降低了不同硬件设备之间的速度差异,防止每次读取时进行实际的读写操作
BufferedInputStream(InputString in );
BuffereOutputStream(OutoutString out);
BuffererdReader/BufferedWriter
BufferedReader(Reader in)
BufferedReader(Reader in, int size)
String readLine()/void newLine()//处理整行的字符数据
对象的序列化与反序列化:实现了对象的持久性 (对象写入磁盘)
Java的对象序列化使得实现了Serialization接口的对象转化成一个字节序列,并使得在之后的过程中这些字符序列仍然能够转化为对象,这一个过程也能够在网络上进行,这使得序列化可以实现在一台计算机上创建的对象在另一台不同操作系统上能够重新组装而不会产生数据的差异。
序列化一个对象的过程:因为对象的序列化是基于字节的,所以先创建一个OutputString对象,然后将其封装在一个ObjectOutputString 中,再调用writeObject()再发送给OutputString即可.
反序列化与之类似。
Point:
1、在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化。
2、通过ObjectOutputStream和ObjectInputStream对对象进行序列化及反序列化(非节点流需要通过其他流来链接数据源)writeObject(对象) readObject()
3、虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID)
4、序列化并不保存静态变量。
5、要想将父类(不只是父类)对象也序列化,就需要让父类也实现Serializable 接口。否则会抛出异常。
6、Transient (瞬时)关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
Transient 只能修饰属性 加上关键字之后,不使用默认的序列化和反序列化方式 用我们重写的方式去序列化和反序列化
7、服务器端给客户端发送序列化对象数据,对象中有一些数据是敏感的,比如密码字符串等,希望对密码字段在序列化时,进行加密,而客户端如果拥有解密的密钥,只有在客户端进行反序列化时,才可以对密码进行读取,这样可以一定程度保证序列化对象的数据安全