Java의 파일 복사 기록
15704 단어 NIO2Commons-IOnioJava
try(InputStream input = new FileInputStream(srcFile);
OutputStream output = new FileOutputStream(dstFile)) {
byte[] buffer = new byte[BUFFER_SIZE];
int size = -1;
while ((size = input.read(buffer)) > 0) {
output.write(buffer, 0, size);
}
}
다른 방법이 뭐가 있겠습니까?파일 복사의 역사를 돌이켜보면commons-io의 실시 변천은 각자의 기법의 기준을 얻으려고 한다.1. 메모리에 모든 버퍼
2002년commons-io의FileUtils에서 처음으로 파일 복제 방법이 나타났을 때, 지금은 이미 얄미운 코드가 되었다.
FileUtils.java
public static void fileCopy(String inFileName, String outFileName) throws
Exception
{
String content = FileUtils.fileRead(inFileName);
FileUtils.fileWrite(outFileName, content);
}
지금 이런 코드를 쓰면 밀려나고...2. InputStream / OutputStream
상술한 방법이 좀 지나치기 때문에 2003년 FileInputStream에서 파일 내용을 읽고 FileOutputStream으로 써서 당시의 정통 설치가 되었다.그럼에도 불구하고 J2SE1.4는 2002년에 발행된 것으로 후술한 FileChannel이 사용할 수 있는 시대다.
https://github.com/apache/commons-io/blob/d9d353082503a217fa6c6510622973d018db0e26/src/java/org/apache/commons/io/FileUtils.java#L604
https://github.com/apache/commons-io/blob/d9d353082503a217fa6c6510622973d018db0e26/src/java/org/apache/commons/io/CopyUtils.java
CopyUtils.java
final byte[] buffer = new byte[bufferSize];
int count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
3. FileChannel (NIO)
FileChannel 은 2008 년에 드디어 사용되기 시작했습니다.
FileUtils.java
private static void doCopyFile(File srcFile, File destFile, boolean preserveFileDate) throws IOException {
if (destFile.exists() && destFile.isDirectory()) {
throw new IOException("Destination '" + destFile + "' exists but is a directory");
}
FileChannel input = new FileInputStream(srcFile).getChannel();
try {
FileChannel output = new FileOutputStream(destFile).getChannel();
try {
output.transferFrom(input, 0, input.size());
} finally {
IOUtils.closeQuietly(output);
}
} finally {
IOUtils.closeQuietly(input);
}
if (srcFile.length() != destFile.length()) {
throw new IOException("Failed to copy full contents from '" +
srcFile + "' to '" + destFile + "'");
}
if (preserveFileDate) {
destFile.setLastModified(srcFile.lastModified());
}
}
commons-io의 현재 트렁크 구현도 이렇지만 윈도큰 파일을 복사할 수 없음(IO-175)에 있기 때문에 30MB마다 트렁크 프롬을 순환한다.4. Files (NIO2)
자바 7에서 NIO2로, 자바로.nio.file.Files 에 copy 메서드가 있습니다.따라서 (파일 복사에 관한)과commons-io는 작별인사를 하고 Files의copy를 직접 사용하면 같은 효과를 기대할 수 있다.
Files.copy(source.toPath(), dest, StandardCopyOption.REPLACE_EXISTING);
기준
그렇다면 이 기준들을 얻어보자.기본 코드는 다음과 같습니다.20MB 파일을 중복 복제할 때의 처리량을 비교합니다.
Linux
디스크 성능의 기계에서
% sync; time bash -c "(dd if=/dev/zero of=bf bs=8k count=500000; sync)"
4096000000 バイト (4.1 GB) コピーされました、 7.00345 秒、 585 MB/秒
결과는 다음과 같다.Benchmark Mode Cnt Score Error Units
InputStream2OutputStream.benchmark thrpt 5 1.669 ± 0.055 ops/s
NIOFileChannel.benchmark thrpt 5 1.860 ± 0.113 ops/s
NIO2Files.benchmark thrpt 5 7.110 ± 1.115 ops/s
Files 를 사용한 복제 방식은 압도적인 빠른 결과입니다.Files가 빠른 이유
Files를 거슬러 올라가는 복제 방법sun.nio.fs.UnixCopyFile은 실제 복제된 것 같다.
private static void copyFile(UnixPath source,
UnixFileAttributes attrs,
UnixPath target,
Flags flags,
long addressToPollForCancel)
throws IOException
{
int fi = -1;
try {
fi = open(source, O_RDONLY, 0);
} catch (UnixException x) {
x.rethrowAsIOException(source);
}
try {
// open new file
int fo = -1;
try {
fo = open(target,
(O_WRONLY |
O_CREAT |
O_EXCL),
attrs.mode());
} catch (UnixException x) {
x.rethrowAsIOException(target);
}
// set to true when file and attributes copied
boolean complete = false;
try {
// transfer bytes to target file
try {
transfer(fo, fi, addressToPollForCancel);
NIO 모드와 마찬가지로 파일을 열어 버퍼 복사를 하지만 오픈으로 거슬러 올라가면sun입니다.misc.Unsafe를 사용하여 로컬 버퍼를 사용합니다.그래서 이렇게 차이가 나는 거야.Windows
Windows로 같은 기준을 재생해 보았습니다.
Benchmark Mode Cnt Score Error Units
InputStream2OutputStream.benchmark thrpt 5 1.032 ± 0.421 ops/s
NIOFileChannel.benchmark thrpt 5 5.466 ± 9.434 ops/s
NIO2Files.benchmark thrpt 5 3.153 ± 2.775 ops/s
FileChannel 및 Filescopy의 결과가 역전되다.Windows에 익숙하지 않아서 이유를 잘 모르겠는데...(Files.copy에서 사용
CopyFileExW
API, 오버헤드입니까?총결산
java.nio.파일의 반은 자바입니다.IO와의 호환성은 약하지만, 네이티브라고 많이 부르는 기능 때문에 성능 면에서 이점이 크다.
특히 거대한 서류와 많은 서류를 처리할 때 적극적으로 사용하는 게 좋지 않겠나.
Reference
이 문제에 관하여(Java의 파일 복사 기록), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kawasima/items/145231e9a51b5c05d589텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)