new IO學習筆記(一)
JDK1.4的java.nio.*包中,引入了新的javaI/O類庫,其目的在於提高速度。
速度的提高來自於使用的結構更接近於操作係統執行I/O的方式:通道和緩衝器。
通道要麼從緩衝中獲得數據,要麼向緩衝器發送數據。
唯一直接與通道交互的緩衝器是ByteBuffer-----也就是說,可以存儲未加工字節的緩衝器。ByteBuffer是個相當基礎的類,通過告知分配多少存儲空間來創建一個ByteBuffer對象,並且還有一個方法選擇集用於以原始的字節形式或基本數據類型輸出和讀取數據。但是沒辦法輸出或讀取對象,即使是字符串對象也不行。
用新I/O來實現對文本文件的拷貝:
FileChannel in = new FileInputStream("d:\\a.txt").getChannel();
FileChannel out = new FileOutputStream("d:\\b.txt").getChannel();
ByteBuffer bb = ByteBuffer.allocate(1024);
while(in.read(bb)!=-1) {
bb.flip();
out.write(bb);
bb.clear();
}
----------------------------------------------------------------------------------------------------------------------------
在NIOZ中提供了特殊的方法transferTo()和transferFrom(),允許我們將一個通道和另一個通道直接連接:
abstract long
transferFrom(ReadableByteChannel src, long position, long count)
將字節從給定的可讀取字節通道傳輸到此通道的文件中。
abstract long
transferTo(long position, long count,WritableByteChannel target)
將字節從此通道的文件傳輸到給定的可寫入字節通道。
FileChannel in = new FileInputStream("d:\\a.txt").getChannel();
FileChannel out = new FileOutputStream("d:\\b.txt").getChannel();
in.transferTo(0,in.size(),out);
//or ---
//out.transferFrom(in,0,in.size());
--------------------------------------------------------------------------------------------------------------------------------
對輸入和輸出的文本進行編碼和解碼
FileChannel out = new FileOutputStream("D:\\a.txt").getChannel();
FileChannel in = new FileInputStream("D:\\a.txt").getChannel(); //兩個FileChannel對象關聯一個文件,一個負責寫,一個讀取
out.write(ByteBuffer.wrap("您好".getBytes("GBK"))); //采用GBK編碼
out.close();
ByteBuffer buf = ByteBuffer.allocate(1024);
in.read(buf);
buf.flip();
in.close();
System.out.println(Charset.forName("gbk").decode(buf)); //輸出時根據GBK解碼
緩衝器容納的是普通的字節,為了把他們轉換成字符,我們要麼在輸入它們的時候對其進行編碼(這樣,它們的輸出才有意義),要麼在將其從緩衝器輸出時對它們進行解碼。
----------------------------------------------------------------------------------------------------------------------------------------------
視圖緩衝器
view buffer可以讓我們通過某個特定的基本數據類型的視窗查看其底層的ByteBuffer。ByteBuffer依然是實際存儲數據的地方,“支持著前麵的視圖”,因此,對視圖的任何修改都會映射成為對ByteBuffer中的數據修改。ByteBuffer中提供了一係列的 " as "方法,用來轉換成各種類型的buffer.
ByteBuffer buf = ByteBuffer.allocate(1024);
IntBuffer ib = buf.asIntBuffer();
ib.put(new int[]{1,3,45,32,34,323,122});
System.out.println(ib.get(3));
ib.put(3, 110);
ib.flip();
while (ib.hasRemaining()) {
System.out.print(ib.get() + ",");
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------
字節存放次序
不同的機器可能會使用不同的字節排序方法來存儲數據。big endian(高位優先)將最重要的字節存放在地址最低的存儲器單元。而 little endian(低位優先)則是將最重要的字節放在地址最高的存儲器單元。ByteBuffer是以高位優先的形式存儲數據的,並且數據在網上傳送時也常常使用高位優先的形式。我們可以使用ByteOrder.BIG_ENDIAN或ByteOrder.LITTLE_ENDIAN的order()方法改變ByteBuffer的字節排序方式。
ByteBuffer buf = ByteBuffer.wrap(new byte[10]);
buf.asCharBuffer().put("abcde");
System.out.println(Arrays.toString(buf.array()));
buf.rewind();
buf.order(ByteOrder.BIG_ENDIAN);
buf.asCharBuffer().put("abcde");
System.out.println(Arrays.toString(buf.array()));
buf.rewind();
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.asCharBuffer().put("abcde");
System.out.println(Arrays.toString(buf.array()));
~~~~~~~~ByteBuffer有足夠的空間,以存儲作為外部緩衝器的CharArray中的所有的字節,因此可以調用array()方法顯示視圖底層的字節。array()方法是可選的,並且我們隻能對由數組支持的緩衝器調用此方法,否則,將會拋出UnsupportedOperationException。
通過CharBuffer視圖可以將charAarry插入到ByteBuffer中,在底層的字節被顯示時,我們會發現默認次序和隨後的高位優先次序相同,然而低位優先次序則與之相反,後者交換了這些字節次序。
-----------------------------------------------------------------------------------------------------------------------------------------------------------
最後更新:2017-04-02 06:51:55