實現一:使用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()+",");
}
}
}
其它類型轉換與上面方法類似,各種方法都相似。