自从jdk1.4以后就引入了NIO文件通道的概念,并且是由io的FileinputStream和FileoutputStream获取
以下代码传入参数
File Copyfile 复制的文件
File newfile 新文件
1.传统IO复制
public static void traditionCopy(File Copyfile, File newfile) throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
byte[] buffer = new byte[2097152];
try {
fis = new FileInputStream(Copyfile);
fos = new FileOutputStream(newfile);
int read = 0;
long startTime = System.currentTimeMillis();
while ((read = fis.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
long EndTime = System.currentTimeMillis();
System.out.print("traditionCopy用了毫秒数:");
System.out.println(EndTime - startTime);
fos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
}
}
2.NIO复制
public static void nioCopy(File Copyfile, File newfile) throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel inFiC = null;
FileChannel outFoC = null;
int length = 2097152;
try {
fis = new FileInputStream(Copyfile);
fos = new FileOutputStream(newfile);
inFiC = fis.getChannel();
outFoC = fos.getChannel();
long startTime = System.currentTimeMillis();
while (inFiC.position() != inFiC.size()) {
if ((inFiC.size() - inFiC.position()) < length) {
length = (int) (inFiC.size() - inFiC.position());// 读取剩下的
}
inFiC.transferTo(inFiC.position(), length, outFoC);
inFiC.position(inFiC.position() + length);
}
long EndTime = System.currentTimeMillis();
System.out.print("nioCopy,用了毫秒总数:");
System.out.println(EndTime - startTime);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outFoC != null) {
outFoC.close();
}
if (inFiC != null) {
inFiC.close();
}
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
}
}
3.NIO文件内存映像复制
public static void nioMappedCopy(File Copyfile, File newfile) throws Exception {
FileInputStream fis = null;
FileOutputStream fos = null;
FileChannel inFiC = null;
FileChannel outFoC = null;
int length = 2097152;
try {
fis = new FileInputStream(Copyfile);
fos = new FileOutputStream(newfile);
inFiC = fis.getChannel();
outFoC = fos.getChannel();
long startTime = System.currentTimeMillis();
while (inFiC.position() != inFiC.size()) {
if ((inFiC.size() - inFiC.position()) < length) {
length = (int) (inFiC.size() - inFiC.position());
}
MappedByteBuffer inbuffer = inFiC.map(MapMode.READ_ONLY, inFiC.position(), length);
outFoC.write(inbuffer);
inFiC.position(inFiC.position() + length);
}
long EndTime = System.currentTimeMillis();
System.out.print("nioMappedCopy用了毫秒数:");
System.out.println(EndTime - startTime);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outFoC != null) {
outFoC.close();
}
if (inFiC != null) {
inFiC.close();
}
if (fos != null) {
fos.close();
}
if (fis != null) {
fis.close();
}
}
}
JAVA NIO中还引入了文件内存映射的概念:现代操作系统大都支持虚拟内存映射,这样,我们可以把内核空间地址与用户空间的虚拟地址映射到同一个物理地址,这样,DMA 硬件(只能访问物理内存地址)就可以填充对内核与用户空间进程同时可见的缓冲区了。
这样做的好处是,我们在读取磁盘文件时,再也不用通过内核缓冲区到用户进程缓冲区的来回拷贝操作了。操作系统会通过一些页面调度算法来将磁盘文件载入对分页区进行高速缓存的物理内存。我们就可以通过映射后物理内存来读取磁盘文件了。
测试mian方法
public static void main(String[] args) throws Exception {
File Copyfile = new File("D:\\test\\eclipse-mars.7z");
File newfilePath = new File("D:\\test\\2\\");
if (!newfilePath.exists()) {
newfilePath.mkdirs();
}
File traditionNewFile = new File(newfilePath + "/" + "traditionCopy.7z");
traditionCopy(Copyfile, traditionNewFile);// traditionCopy用了毫秒数:644
File nioNewFile = new File(newfilePath + "/" + "nioCopy.7z");
nioCopy(Copyfile, nioNewFile);// nioCopy,复制文件用了毫秒总数:283
File nioMappedNewFile = new File(newfilePath + "/" + "nioMappedCopy.7z");
nioMappedCopy(Copyfile, nioMappedNewFile);//nioMappedCopy用了毫秒数:266
}
因此,不考虑多线程优化,单线程文件复制最快的方法是NIO文件内存映像复制。
PS:终于写完了。希望以后的自己看到这代码要说一句:这破代码谁写的。哈哈。