java nio 文件_Java nio 的文件处理
一、創建一個大文件
下載文件時往往會創建一個指定大小的空文件
package com.lazy.nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* 創建大文件
* @author Lazy Gene
*
*/
public class FileCreator {
public static void main(String[] args) {
FileCreator creator = new FileCreator();
creator.createBigEmptyFile();
}
void createBigEmptyFile(){
Path filePath = Paths.get("from/test.tmp");
// 這段代碼實際上可以在FIleChannel 調用open方式時指定OpenOption 為Create_NEW
try {
if (!Files.exists(filePath)) {
Files.createFile(filePath);
}
} catch (IOException e1) {
e1.printStackTrace();
}
//寫一個字節
ByteBuffer buffer = ByteBuffer.allocate(1);
try (FileChannel fileChannel = FileChannel.open(filePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
fileChannel.position(2L << 32 - 1); //移動位置, 生成一個4G的空文件
fileChannel.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
二、文件轉移
NIO 提供transferTo tansferFrom, 和傳統的文件訪問方式相比減少了數據從內核到用戶空間的復制,數據直接在內核移動,在Linux系統中使用sendfile系統調用
這里分別通過FileChannel.transferFrom 和Files.copy以及普通的io調用實現文件的復制
package com.lazy.nio;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* 文件轉移
*
* @author Lazy Gene(ljgeng@iflytek.com)
*
*/
public class FileTransfer {
Path fromPath = Paths.get("from/test.tmp");
Path toPath = Paths.get("to/test.tmp");
public static void main(String[] args) throws IOException {
FileTransfer transfer = new FileTransfer();
long start = System.currentTimeMillis();
transfer.transferFrom();
long end1 = System.currentTimeMillis();
System.out.println("transferFrom: "+ (end1 - start));
Files.deleteIfExists(transfer.toPath);
transfer.copy();
long end2 = System.currentTimeMillis();
System.out.println("Files copy: "+(end2 - end1));
Files.deleteIfExists(transfer.toPath);
transfer.ioCopy();
long end3 = System.currentTimeMillis();
System.out.println("original io: "+(end3 - end2));
}
void transferFrom() {
try (FileChannel channelFrom = FileChannel.open(fromPath, StandardOpenOption.READ);
FileChannel channelTo = FileChannel.open(toPath, StandardOpenOption.CREATE_NEW,
StandardOpenOption.WRITE);) {
channelTo.transferFrom(channelFrom, 0L, channelFrom.size());
} catch (IOException e) {
e.printStackTrace();
}
}
void copy() {
try {
Files.copy(fromPath, toPath);
} catch (IOException e) {
e.printStackTrace();
}
}
void ioCopy() {
try (InputStream is = new FileInputStream(fromPath.toFile());
OutputStream os = new FileOutputStream(toPath.toFile());) {
byte[] buffer = new byte[4096];
int byteread = 0;
while ((byteread = is.read(buffer)) != -1) {
os.write(buffer, 0, byteread);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
執行結果
transferFrom: 32726
Files copy: 33002
original io: 112975
將ioCopy方法中每次讀取字節數調大十倍和百倍后結果
original io: 54743 (十倍)
original io: 93110 (百倍)
三、FileChannel.map 的使用
FileChannel.map 將文件按照一定大小塊映射到內存區域,程序方式內存區域操作文件,適合大文件只讀操作,如大文件的md5校驗。
package com.lazy.nio;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* 使用介紹
* @author Lazy Gene
*
*/
public class FileChannelMap {
public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
// 計算test.tmp 的md5值,將文件分成多塊計算
Path path = Paths.get("from/test.tmp");
File file = path.toFile();
RandomAccessFile accessFile = new RandomAccessFile(file, "r");
MessageDigest MD5 = MessageDigest.getInstance("MD5");
long start = System.currentTimeMillis();
long eachSize = 1024 * 1024L;
long length = file.length();
int count = 1 + (int) (length / eachSize); //分塊數量
long remaining = length; // 剩下的大小
for (int i=0;i
MD5.update(accessFile.getChannel().map(FileChannel.MapMode.READ_ONLY, i * eachSize, Math.min(remaining, eachSize)));
remaining -= eachSize;
}
accessFile.close();
long end = System.currentTimeMillis();
System.out.println("用時:"+(end - start));
System.out.println("md5: "+ new String(Hex.encodeHex(MD5.digest())));
//方法二
MessageDigest new_MD5 = MessageDigest.getInstance("MD5");
FileInputStream in=new FileInputStream(file);
byte[] buffer=new byte[65536];
int rv=0;
while((rv=in.read(buffer))>0) {
new_MD5.update(buffer,0,rv);
}
long end1 = System.currentTimeMillis();
in.close();
System.out.println("用時:"+(end1 - end));
System.out.println("io md5: "+ new String(Hex.encodeHex(new_MD5.digest())));
}
}
對于4g文件運行結果:
用時:15172
md5: f18c798ff5d450dfe4d3acdc12b621ff
用時:15811
io md5: f18c798ff5d450dfe4d3acdc12b621ff
差別不大呀,將文件調到16g,運行結果
用時:65046
md5: 0eb76b1bf69255feec7bdf4a3b5e2805
用時:62697
io md5: 0eb76b1bf69255feec7bdf4a3b5e2805
這里只所以差別不大,估計是應用map操作和操作系統的底層io實現相關,下次換成linux看看。
總結
以上是生活随笔為你收集整理的java nio 文件_Java nio 的文件处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java get方法不序列化_java常
- 下一篇: java继承与实现的_[Java学习]