Java nio 學習筆記(三)
阿新 • • 發佈:2018-12-25
實現一:使用nio實現檔案複製
package study.nio; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.ByteBuffer; public class TestCopyFile { public static void main(String[] args) throws IOException { //呼叫FileManager類的copyFile靜態方法 FileManager.copyFile(new File("src.txt"), new File("dst.txt")); } } class FileManager { //把可能出現的異常拋給上層呼叫者處理 public static void copyFile(File src, File dst) throws FileNotFoundException, IOException { //得到一個原始檔對應的輸入通道 FileChannel fcin = new FileInputStream(src).getChannel(); //得到一個目標檔案對應的輸出通道 FileChannel fcout = new FileOutputStream(dst).getChannel(); //生成一個1024位元組的ByteBuffer例項 ByteBuffer buf = ByteBuffer.allocate(1024); while(fcin.read(buf) != -1) { buf.flip(); //準備寫 fcout.write(buf); buf.clear(); //準備讀 } } }
還可以使用下面方式進行操作,在FileChannel中有兩個特殊方法可以允許我們直接將兩個通道相連:
long transferFrom(ReadableByteChannel src, long position, long count);
long transferTo(long position, long count, WriteableByteChannel targets);
上面while迴圈可以替換為:
fcin.transferTo(0, fcin.size(), fcout); 或者 fcout.transferFrom(fcin, 0, fcin.size());
實現二:向一個空檔案中寫入some text,再以只讀方式開啟該檔案,在尾部追加some more,最終將該檔案內容輸出。
package study.nio; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class GetChannel { //為了使程式碼明晰,暫不處理異常 public static void main(String[] args) throws Exception { FileChannel fc = null; //向一個檔案中寫入文字 fc = new FileOutputStream(new File("data.txt")).getChannel(); fc.write(ByteBuffer.wrap("some text".getBytes())); fc.close(); //以讀寫方式開啟檔案,並在尾部追加內容 fc = new RandomAccessFile("data.txt", "rw").getChannel(); fc.position(fc.size()); fc.write(ByteBuffer.wrap("some more".getBytes())); fc.close(); //將檔案裡的內容讀出來 fc = new FileInputStream("data.txt").getChannel(); ByteBuffer buf = ByteBuffer.allocate(1024); fc.read(buf); buf.flip(); while(buf.hasRemaining()) { System.out.print((char)buf.get()); } } }
以上均使用的是位元組操作流,與nio相一致。Reader和Writer這些字元模式類不能用於產生通道,但是java.nio.channels.Channels類中提供了實用方法,可以在通道中產生Reader和Writer。
Channels.newReader();
Channels.newWriter();
實現三:將一個大檔案對映到記憶體並查詢指定的文字內容是否在該檔案中(曾記得李開復與微軟的故事,當然李開復是從郵件中查詢資訊,並且郵件被截成了圖片,⊙﹏⊙b汗)
public class LargeMappedFiles {
public static void main(String args[]) {
try {
File[] files = new File[] {new File("src1.txt"), new File("src2.txt")};
ArrayList<String> ls = search(files, "something is wrong");
for(int i=0; i<ls.size(); i++) {
System.out.println(ls.get(i));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
//實現簡單的內容檢索
private static ArrayList<String> search(File[] files, String text) throws Exception {
//把檢索結果放到一個list中
ArrayList<String> result = new ArrayList<String>();
//迴圈遍歷檔案
for(File src : files) {
//將整個檔案對映到記憶體
MappedByteBuffer dst = new RandomAccessFile(src, "rw")
.getChannel()
.map(FileChannel.MapMode.READ_WRITE, 0, src.length());
//對字元進行解碼
String str = Charset.forName("UTF-8").decode(dst).toString();
//準備進行讀
dst.flip();
if(str.indexOf(text) != -1) {
result.add(src.getName());
}
//準備寫
dst.clear();
}
return result;
}
}
實現四:在前面的學習中瞭解到nio為所有原始資料型別提供了Buffer支援,並且在ByteBuffer中實現了asXBuffer()方法直接將一個ByteBuffer轉換成其它型別的Buffer。本例實現資料型別的轉換。
import java.nio.IntBuffer;
import java.nio.FloatBuffer;
import java.nio.ByteBuffer;
import java.util.Arrays;
public class CastBuffer {
static byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5, 'a', 'b', 'c'};
public static void main(String[] args) {
ByteBuffer bBuf = ByteBuffer.wrap(bytes);
System.out.println(Arrays.toString(bBuf.array()));
//轉換成IntBuffer
IntBuffer iBuf = ((ByteBuffer)bBuf.rewind()).asIntBuffer();
while(iBuf.hasRemaining()) {
System.out.print(iBuf.get()+",");
}
//轉換成FloatBuffer
FloatBuffer fBuf = ((ByteBuffer)bBuf.rewind()).asFloatBuffer();
while(fBuf.hasRemaining()) {
System.out.print(fBuf.get()+",");
}
}
}
其它型別轉換與上面方法類似,各種方法都相似。