在java中对于文件的操作,存在两种方式,一种是阻塞的java.io.*
,另外一种则是非阻塞的java.nio.*
下面给出几种不同方法实现文件copy的代码:
import org.junit.Before;
import org.junit.Test;
import org.springframework.util.FileCopyUtils;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
/**
* Created with IntelliJ IDEA.
*
* @author: richard_xsyao
* @date: 2018/9/13 11:36
* Description:
*/
public class FileCopyTest {
private String filePath = null;
private String copyFilePath = null;
@Before
public void initFilePath() {
filePath = "E:\\var\\test.zip";
copyFilePath = "E:\\var\\copy.zip";
File copyFile = new File(copyFilePath);
if(copyFile.exists()) {
copyFile.delete();
}
}
@Test
public void testFileCopyWithCommonIo() {
long startTime = System.currentTimeMillis();
File file = new File(filePath);
try {
InputStream fileStream = new FileInputStream(file);
OutputStream outputStream = new FileOutputStream(new File(copyFilePath));
byte[] bytes = new byte[1024];
int length = 0;
while((length = fileStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, length);
}
fileStream.close();
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long costTime = endTime - startTime;
System.out.println("Copy file with stream cost time: " + costTime);
}
@Test
public void testFileCopyWithNioUtil() {
long startTime = System.currentTimeMillis();
File originFile = new File(filePath);
File copyFile = new File(copyFilePath);
try {
// This copy method actually using newInputStream to read data and write into newOutputStream
FileCopyUtils.copy(originFile, copyFile);
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long costTime = endTime - startTime;
System.out.println("Copy file with Spring FileCopyUtils: " + costTime);
}
@Test
public void testFileCopyWithNioChannel() {
long startTime = System.currentTimeMillis();
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
FileInputStream inputStream = new FileInputStream(new File(filePath));
FileOutputStream outputStream = new FileOutputStream(new File(copyFilePath));
// Using FileChannel's transfer method to transfer bytes
inputChannel = inputStream.getChannel();
outputChannel = outputStream.getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
inputStream.close();
outputStream.close();
inputChannel.close();
outputChannel.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long costTime = endTime - startTime;
System.out.println("Copy file with Nio channel: " + costTime);
}
@Test
public void testFileCopyWithFiles() {
long startTime = System.currentTimeMillis();
File originFile = new File(filePath);
File copyFile = new File(copyFilePath);
try {
Files.copy(originFile.toPath(), copyFile.toPath());
} catch (IOException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
long costTime = endTime - startTime;
System.out.println("Copy file with Java Files: " + costTime);
}
}
最常见的就是使用InputStream和OutputStream,将数据从文件系统读入到内存buffer,然后从buffer copy到中间缓存区如数组,然后再将数据输出到指定文件中;缺点:操作繁琐,对于大文件操作会很低效,还需要在结束后手动关闭流。如上面testFileCopyWithCommonIo()
方法所示。
Java在jdk1.4之后提供了nio包来提高io性能,使用FileChannel
的transferFrom
或者transferTo
方法将数据直接输出到文件系统而无需额外的内存缓存:Many operating systems can transfer bytes directly from the filesystem cache to the target channel without actually copying them
网友评论