Guava ByteSreams 常用方法的封裝,FileInputStream的兄弟ByteArrayInputSteam,裝飾類大兄弟DataOutputStream
ByteArrayInputSteam
JDK解釋:一個從位元組陣列讀取的輸入流包含一個內部緩衝區包含的位元組,可以從流中讀取。內部計數器跟蹤由讀方法提供的下一個位元組。Closing a ByteArrayInputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.
ByteArrayInputStream(byte[] buf) 引數buf指定位元組陣列型別的資料來源。 ByteArrayInputStream(byte[] buf, int offset, int lenght) 引數buf指定位元組陣列型別資料來源,引數offset指定從陣列中開始讀取資料的起始下標位置,lenght指定從陣列中讀取的位元組數。
ByteArrayInputStream類本身採用了介面卡設計模式,它把位元組陣列型別轉換為輸入流型別,使得程式能夠對位元組陣列進行讀操作。這個和FileInputStream差不多,將File轉換為位元組流。
原始碼:這裡的mark 和 pos和NIO中的有點類似哦!將資料從byte[]轉換為Inputstream的包裝類?哈哈沒有使用過誒,看Guava的原始碼中才看到這個的使用。
public class ByteArrayInputStream extends InputStream {
protected byte buf[];
protected int pos;
protected int mark = 0;
protected int count;
public ByteArrayInputStream(byte buf[]) {
this .buf = buf;
this.pos = 0;
this.count = buf.length;
}
public ByteArrayInputStream(byte buf[], int offset, int length) {
this.buf = buf;
this.pos = offset;
this.count = Math.min(offset + length, buf.length);
this.mark = offset;
}
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
if (pos >= count) {
return -1;
}
int avail = count - pos;
if (len > avail) {
len = avail;
}
if (len <= 0) {
return 0;
}
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public synchronized long skip(long n) {
long k = count - pos;
if (n < k) {
k = n < 0 ? 0 : n;
}
pos += k;
return k;
}
/**
* Returns the number of remaining bytes that can be read
*(or skipped over)
* from this input stream.
*/
public synchronized int available() {
return count - pos;
}
public void mark(int readAheadLimit) {
mark = pos;
}
public synchronized void reset() {
pos = mark;
}
/**
* Closing a <tt>ByteArrayInputStream</tt> has no effect. The methods in
* this class can be called after the stream has been closed without
* generating an <tt>IOException</tt>.
*/
public void close() throws IOException {
}
}
DataOutputStream繼承FilterOutputStream(包裝類都繼承這個)
FilterOutputStream裝飾類的核心
public class FilterOutputStream extends OutputStream {
protected OutputStream out;
public FilterOutputStream(OutputStream out) {
this.out = out;
}
public void write(int b) throws IOException {
out.write(b);
}
}
是Java中輸入輸出流的裝飾類
A data output stream lets an application write primitive Java data(原生的Java資料資訊到位元組流中,提供了一種便利的方式) types to an output stream in a portable way. An application can then use a data input stream to read the data back in.
什麼是原生的資料資訊呢?int,short,long,double,string等等,因為輸入到流中是使用位元組為單元的,比如int是4個位元組,要使用包裝類才方便得到位元組陣列,那麼原生的資料資訊就需要自己一個個位元組的寫入啦,非常的不方便,所以這個的意義也是在於處理這些資料資訊哦!
writeInt:Writes an int to the underlying output stream as four bytes, high byte first. 這個的處理可以看懂吧,就是簡單的處理int的四個位元組。
public final void writeInt(int v) throws IOException { out.write((v >>> 24) & 0xFF); out.write((v >>> 16) & 0xFF); out.write((v >>> 8) & 0xFF); out.write((v >>> 0) & 0xFF); incCount(4); }
- WriteUTF更加的好玩一些,因為UTF-8的編碼方式,有的使用一個位元組,有的使用二個位元組,有的使用三個位元組,所有在DataOutputStream處理中首先是處理String的長度轉換為UTF-8需要多少位元組,然後在前兩位寫入資料的長度,後面才開始處理資料資訊。這些DataInputStrem都幫我們進行了處理所以使用起來非常的方便。
- WriteUTF 計算長度
for (int i = 0; i < strlen; i++) {
c = str.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) { //1-127
utflen++;
} else if (c > 0x07FF) {
utflen += 3;
} else {
utflen += 2;
}
}
// Data Stream寫到輸入流中
DataOutputStream dos = new DataOutputStream(new FileOutputStream(
"datasteam.txt"));
//按2位元組寫入,都是寫入的低位
dos.writeBytes("世界");
// 按照Unicode寫入 JDK預設的方式
dos.writeChars("世界");
// 按照UTF-8寫入UTF8變長
//開頭2位元組是由writeUTF函式寫入的長度資訊,
方便readUTF函式讀取)
dos.writeUTF("世界");
dos.flush();
dos.close();
```
* writeBytes這裡進行了強制轉換,肯定會丟失精度的。
```
public final void writeBytes(String s) throws IOException {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
out.write((byte)s.charAt(i));
}
incCount(len);
}
- writeChars這個就好理解的,兩個位元組處理。
public final void writeChars(String s) throws IOException {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
int v = s.charAt(i);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
}
incCount(len * 2);
}
Guava ByteStreams 處理位元組流資訊
提供了一些非常有用的方法,感覺還不錯,比如複製位元組流到一個另外的一個輸出流,將inputStream轉換為byte資料
* copy:
public static long copy(InputStream from, OutputStream to) throws IOException {
checkNotNull(from);
checkNotNull(to);
byte[] buf = new byte[8192];
long total = 0;
while (true) {
int r = from.read(buf);
if (r == -1) {
break;
}
to.write(buf, 0, r);
total += r;
}
return total;
}
- 轉換為byte陣列:是不是很方便!其他的方法不想使用了就這兩個非常的可以的!
public static byte[] toByteArray(InputStream in) throws IOException {
// Presize the ByteArrayOutputStream since we know how large it will need
// to be, unless that value is less than the default ByteArrayOutputStream
// size (32).
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(32, in.available()));
copy(in, out);
return out.toByteArray();
}
總結
對於流資訊的認識更加深了一份理解.