Java的Channel通道之FileChannel類詳解
Channel(通道)之FileChannel類
- FileChannel類的基本使用 獲取FileChannel類的對(duì)象
- java.nio.channels.FileChannel (抽象類):用于讀、寫文件的通道
- FileChannel是抽象類,我們可以通過FileInputStream和FileOutputStream的getChannel()方法方便的獲取一個(gè)它的子類對(duì)象。
FileInputStream fi=new FileInputStream(new File(src)); FileOutputStream fo=new FileOutputStream(new File(dst)); //獲得傳輸通道channel FileChannel inChannel=fi.getChannel(); FileChannel outChannel=fo.getChannel();
使用FileChannel類完成文件的復(fù)制
public static void main(String[] args) throws Exception{ FileInputStream fis = new FileInputStream("a.txt"); FileOutputStream fos = new FileOutputStream("aCopy1.txt"); // 獲得FileChannel管道對(duì)象 FileChannel c1 = fis.getChannel(); FileChannel c2 = fos.getChannel(); // 創(chuàng)建ByteBuffer數(shù)組 ByteBuffer b = ByteBuffer.allocate(1000); // 循環(huán)讀取數(shù)據(jù) while ((c1.read(b)) != -1){// 讀取的字節(jié)會(huì)填充postion到limit位置之間 // 重置 postion為0,limit為postion的位置 b.flip(); // 寫出數(shù)據(jù) c2.write(b);// 會(huì)把postion到limit之間的數(shù)據(jù)寫出 // 還原 b.clear();// positon為:0 limit為: capacity 用于下次讀取 } // 釋放資源 c2.close(); c1.close(); fos.close(); fis.close(); /*byte[] bys = new byte[8192]; int len; while ((len = fis.read(bys)) != -1){ fos.write(bys,0,len); } fos.close(); fis.close();*/ }
FileChannel結(jié)合MappedByteBuffer實(shí)現(xiàn)高效讀寫
MappedByteBuffer類
- 使用FileChannel結(jié)合ByteBuffer實(shí)現(xiàn)的管道讀寫,但并不能提高文件的讀寫效率。
- ByteBuffer有個(gè)抽象子類:MappedByteBuffer,它可以將文件直接映射至內(nèi)存,把硬盤中的讀寫變成內(nèi)存中的讀寫, 所以可以提高大文件的讀寫效率
- 可以調(diào)用FileChannel的map()方法獲取一個(gè)MappedByteBuffer,map()方法的原型: MappedByteBuffer map(MapMode mode, long position, long size); 說明:將節(jié)點(diǎn)中從position開始的size個(gè)字節(jié)映射到返回的MappedByteBuffer中
//復(fù)制2GB以下的文件 //map的第三個(gè)參數(shù)被限制在Integer.MAX_VALUE(字節(jié)) = 2G
public static void main(String[] args) throws Exception{ //java.io.RandomAccessFile類,可以設(shè)置讀、寫模式的IO流類。 //"r"表示:只讀--輸入流,只讀就可以。 RandomAccessFile r1 = new RandomAccessFile("a.txt","r"); //"rw"表示:讀、寫--輸出流,需要讀、寫。 RandomAccessFile r2 = new RandomAccessFile("aCopy2.txt","rw"); // 獲得FileChannel管道對(duì)象 FileChannel c1 = r1.getChannel(); FileChannel c2 = r2.getChannel(); // 獲取文件的大小 long size = c1.size(); // 直接把硬盤中的文件映射到內(nèi)存中 MappedByteBuffer b1 = c1.map(FileChannel.MapMode.READ_ONLY, 0, size); MappedByteBuffer b2 = c2.map(FileChannel.MapMode.READ_WRITE, 0, size); // 循環(huán)讀取數(shù)據(jù) for (long i = 0; i < size; i++) { // 讀取字節(jié) byte b = b1.get(); // 保存到第二個(gè)數(shù)組中 b2.put(b); } // 釋放資源 c2.close(); c1.close(); r2.close(); r1.close(); }
//下例使用循環(huán),將文件分塊,可以高效的復(fù)制大于2G的文件
public static void main(String[] args) throws Exception{ //java.io.RandomAccessFile類,可以設(shè)置讀、寫模式的IO流類。 //"r"表示:只讀--輸入流,只讀就可以。 RandomAccessFile r1 = new RandomAccessFile("H:\\資料.zip","r"); //"rw"表示:讀、寫--輸出流,需要讀、寫。 RandomAccessFile r2 = new RandomAccessFile("H:\\資料2.zip","rw"); // 獲得FileChannel管道對(duì)象 FileChannel c1 = r1.getChannel(); FileChannel c2 = r2.getChannel(); // 獲取文件的大小 long size = c1.size(); // 每次期望復(fù)制500M int everySize = 1024*1024*500; // 總共需要復(fù)制多少次 long count = size % everySize == 0 ? size/everySize : size/everySize+1; // 開始復(fù)制 for (long i = 0; i < count; i++) { // 每次開始復(fù)制的位置 long start = everySize*i; // 每次復(fù)制的實(shí)際大小 long trueSize = size - start > everySize ? everySize : size - start; // 直接把硬盤中的文件映射到內(nèi)存中 MappedByteBuffer b1 = c1.map(FileChannel.MapMode.READ_ONLY, start, trueSize); MappedByteBuffer b2 = c2.map(FileChannel.MapMode.READ_WRITE, start, trueSize); // 循環(huán)讀取數(shù)據(jù) for (long j = 0; j < trueSize; j++) { // 讀取字節(jié) byte b = b1.get(); // 保存到第二個(gè)數(shù)組中 b2.put(b); } } // 釋放資源 c2.close(); c1.close(); r2.close(); r1.close(); }
ServerSocketChannel和SocketChannel創(chuàng)建連接
SocketChannel創(chuàng)建連接
- 客戶端:SocketChannel類用于連接的客戶端,它相當(dāng)于:Socket。
ServerSocketChanne創(chuàng)建連接
- 服務(wù)器端:ServerSocketChannel類用于連接的服務(wù)器端,它相當(dāng)于:ServerSocket 服務(wù)器代碼
public class Server { public static void main(String[] args) throws IOException{ //創(chuàng)建對(duì)象 //ServerSocket ss = new ServerSocket(8888); //創(chuàng)建 ServerSocketChannel ssc = ServerSocketChannel.open(); //服務(wù)器綁定端口 ssc.bind(new InetSocketAddress(8888)); //連接上客戶端 SocketChannel sc = ssc.accept(); //服務(wù)器端接受數(shù)據(jù) //創(chuàng)建數(shù)組 ByteBuffer buffer = ByteBuffer.allocate(1024); //接收數(shù)據(jù) int len = sc.read(buffer); //打印結(jié)構(gòu) System.out.println(new String(buffer.array(),0,len)); //關(guān)閉資源 sc.close(); } }
客戶端代碼
public class Client { public static void main(String[] args) { //創(chuàng)建對(duì)象 //Socket s = new Socket("127.0.0.1",8888); //創(chuàng)建對(duì)象 SocketChannel sc = SocketChannel.open(); //連接服務(wù)器 sc.connect(new InetSocketAddress("127.0.0.1",8888)); //客戶端發(fā)數(shù)據(jù) //創(chuàng)建數(shù)組 ByteBuffer buffer = ByteBuffer.allocate(1024); //數(shù)組中添加數(shù)據(jù) buffer.put("你好".getBytes()); //切換 buffer.flip(); //發(fā)出數(shù)據(jù) sc.write(buffer); //關(guān)流 sc.close(); } }
到此這篇關(guān)于Java的Channel通道之FileChannel類詳解的文章就介紹到這了,更多相關(guān)Java的FileChannel類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
初步學(xué)習(xí)Java中線程的實(shí)現(xiàn)與生命周期
這篇文章主要介紹了初步學(xué)習(xí)Java中線程的實(shí)現(xiàn)與生命周期,線程方面的知識(shí)是Java學(xué)習(xí)過程中的重點(diǎn)和難點(diǎn),需要的朋友可以參考下2015-11-11Java基于JNDI 實(shí)現(xiàn)讀寫分離的示例代碼
本文主要介紹了Java基于JNDI 實(shí)現(xiàn)讀寫分離的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12JAVA實(shí)現(xiàn)sm3加密簽名以及防止重復(fù)攻擊
這篇文章主要給大家介紹了關(guān)于JAVA實(shí)現(xiàn)sm3加密簽名以及防止重復(fù)攻擊的相關(guān)資料,SM3是簽名算法,和MD5一樣(對(duì)于應(yīng)用層來說),SM4是對(duì)稱加密算法,和AES一樣(對(duì)于應(yīng)用層來說),需要的朋友可以參考下2023-10-10Spring-AOP 靜態(tài)正則表達(dá)式方法如何匹配切面
這篇文章主要介紹了Spring-AOP 靜態(tài)正則表達(dá)式方法如何匹配切面的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07解決SpringBoot集成Eureka導(dǎo)致返回結(jié)果由json變?yōu)閤ml的問題
這篇文章主要介紹了解決SpringBoot集成Eureka導(dǎo)致返回結(jié)果由json變?yōu)閤ml的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07java如何實(shí)現(xiàn)判斷文件的真實(shí)類型
本篇文章主要介紹了java如何實(shí)現(xiàn)判斷文件的真實(shí)類型,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08