如果安卓8.0(API26)以上的系统,建议使用java.nio.file.Files.copy()方法。
因为如果在同一个文件系统上的话,Files.copy会调用系统的复制文件方法,此时性能开销最小。
连缓存块的操作都不需要,直接由系统内核在DMA(Direct Memory Access)处操作。
如果两个文件不在一个文件系统上,比如一个是磁盘,一个是网络,则使用buffers缓冲区复制文件。
使用方法如下:
try {
// 同一个系统的话,使用系统的复制功能,否则使用buffers复制
Files.copy(in.toPath(), out.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
如果安卓8.0(API26)以下的系统上,建议使用java.nio.filechannel复制文件。
因为nio都是块操作,有buffer,并且可以实现零拷贝。远比旧的Stream IO跑到用户空间调用系统的read()/write()方法,额外消耗cpu资源的方式好多了。
// 自动关闭资源的写法,实现closeable的资源
try (FileChannel src = new FileInputStream(in).getChannel(); FileChannel dst = new FileOutputStream(out).getChannel()) {
dst.transferFrom(src, 0, src.size());
} catch (Exception e) {
e.printStackTrace();
}
如果需要修改文件内容的话,使用mapper,映射到内存,此时映射的内容会直接由系统的页缓存管理,当发生修改的时候,系统页缓会存标记修改的内容为脏数据,进而触发刷写到内存。单纯的复制文件则没必要使用。
MappedByteBuffer mbb = sourceCh.map(FileChannel.MapMode.READ_ONLY, 0, sourceCh.size());