Java 3: IO Stream
IO Stream 核心方法
InputStream类
read():int
read(byte[]) :int
read(byte[],int,int):int
OutputStream类
write(int):void //写入int(32位 4个字节)的低8位,其他24个字节将被忽略
write(byte[]):void
write(byte[],int,int):void
Reader类
read(Charbuffer):int
read():int
read(char[]):int
read(char[],int,int):int
Writer类
wirte(int):void //写入一个character( int 32位,但是char 16位 ,2个字节)的低16位,高16位将被忽略
wirte(char[]):void
wirte(char[],int ,int):void
write(String):void
write(String,int,int):void
FileInputStream
FileOutputStream
DataInputStream
DataOutputStream
DataXXX 是InputStream,OutputStream的包装类,基于InputStream,OutputStream提供了很多操作数据的方法,比如操作int,string等;
BufferedInputStream
BufferedOutputStream
字节流
1: 单一字节读取 ;
2:批量读取(自定义数组大小);
3:使用Buffered,BufferedInputStream中。原理是:先单字节读取到buffer中,在从buffer中转移到目标位置;
BufferedInputStream 中使用buffer减少访问磁盘的次数,达到提升性能;
其中批量读取最高效;
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
/**
* Fills the buffer with more data, taking into account
* shuffling and other tricks for dealing with marks.
* Assumes that it is being called by a synchronized method.
* This method also assumes that all data has already been read in,
* hence pos > count.
*/
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
if (markpos < 0)
pos = 0; /* no mark: throw away the buffer */
else if (pos >= buffer.length) /* no room left in buffer */
if (markpos > 0) { /* can throw away early part of the buffer */
int sz = pos - markpos;
System.arraycopy(buffer, markpos, buffer, 0, sz);
pos = sz;
markpos = 0;
} else if (buffer.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
} else if (buffer.length >= MAX_BUFFER_SIZE) {
throw new OutOfMemoryError("Required array size too large");
} else { /* grow buffer */
int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
pos * 2 : MAX_BUFFER_SIZE;
if (nsz > marklimit)
nsz = marklimit;
byte nbuf[] = new byte[nsz];
System.arraycopy(buffer, 0, nbuf, 0, pos);
if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
// Can't replace buf if there was an async close.
// Note: This would need to be changed if fill()
// is ever made accessible to multiple threads.
// But for now, the only way CAS can fail is via close.
// assert buf == null;
throw new IOException("Stream closed");
}
buffer = nbuf;
}
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos); // 这里是真正读内容的地方
if (n > 0)
count = n + pos;
}
字符流
1:编码问题
2:文本,文本文件
文本:Java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码 2字节 16位);
文件: byte byte byte ... 的数据序列
文本文件:文本文件是文本(char)按照某种编码方案(utf-8,utf-16be,gbk)序列号为byte的存储结果;
3:字符流(Reader,Writer)
字符的处理,一次处理一个字符
字符的底层基本的字节序列;
InputStreamReader / OutputStreamWriter
InputStreamReader OutputStreamWriter是字符流和字节流的桥梁,提供需要解析编码时的转换;
InputStreamReader:实现输入的字节流(byte)解析为字符流(char),按照编码解析; OutputStreamWriter:实现输出的字符流(char)解析为字节流(byte),按照编码解析;
FileReader / FileWriter
BufferedReader / BufferedWriter,PrinterWriter
序列化
1:对象序列化:是将Object 转换为byte序列,反之叫对象的反序列化;
2:序列化流 ObjectOutputStream,ObjectInputStream. 关键反复writerObject,readObject;
3:序列化需要实现序列化接口(Serializable)
序列化 - transient 关键字
加了transient 关键字 ,那么该元素不会进行jvm默认的序列化;
ArrayList 中的 transient 序列化
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/
transient Object[] elementData; // non-private to simplify nested class access
}
ArrayList 中的 对 标有transient关键字的元素进行序列化
/**
* Save the state of the <tt>ArrayList</tt> instance to a stream (that
* is, serialize it).
*
* @serialData The length of the array backing the <tt>ArrayList</tt>
* instance is emitted (int), followed by all of its elements
* (each an <tt>Object</tt>) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); //1: 第一步使用默认的序列化
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]); //第二步 只序列化有用的元素
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
/**
* Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
* deserialize it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject(); //1: 第一步 使用默认的序列化
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject(); //2:第二部 只序列化有用的元素
}
}
}
序列化父子类
1:父类实现了序列化接口,子类也能实现序列化;
2:子类需要实现序列化,只需要子类实现序列化接口,父类不一定要实现序列化接口
3:对子类对象进行反序列化操作时,如果父类没有实现序列化接口,那么其父类的构造函数会被显示的调用;如果父类实现了序列化接口,反序列化可以直接读取到构造中的内容,无需显示调用;