一直困扰我的是,在Java中复制文件的唯一方法包括打开流,声明缓冲区,读入一个文件,循环遍历它,并将其写入到另一个steam。网络上充斥着类似的,但仍然略有不同的这类解决方案的实现。
是否有一种更好的方法能够保持在Java语言的范围内(即不涉及执行特定于操作系统的命令)?也许在一些可靠的开源实用程序包中,它至少会模糊这个底层实现,并提供一行解决方案?
一直困扰我的是,在Java中复制文件的唯一方法包括打开流,声明缓冲区,读入一个文件,循环遍历它,并将其写入到另一个steam。网络上充斥着类似的,但仍然略有不同的这类解决方案的实现。
是否有一种更好的方法能够保持在Java语言的范围内(即不涉及执行特定于操作系统的命令)?也许在一些可靠的开源实用程序包中,它至少会模糊这个底层实现,并提供一行解决方案?
当前回答
public static void copyFile(File src, File dst) throws IOException
{
long p = 0, dp, size;
FileChannel in = null, out = null;
try
{
if (!dst.exists()) dst.createNewFile();
in = new FileInputStream(src).getChannel();
out = new FileOutputStream(dst).getChannel();
size = in.size();
while ((dp = out.transferFrom(in, p, size)) > 0)
{
p += dp;
}
}
finally {
try
{
if (out != null) out.close();
}
finally {
if (in != null) in.close();
}
}
}
其他回答
现在在Java 7中,你可以使用下面的try-with-resource语法:
public static void copyFile( File from, File to ) throws IOException {
if ( !to.exists() ) { to.createNewFile(); }
try (
FileChannel in = new FileInputStream( from ).getChannel();
FileChannel out = new FileOutputStream( to ).getChannel() ) {
out.transferFrom( in, 0, in.size() );
}
}
或者,更好的是,这也可以使用Java 7中引入的新Files类来完成:
public static void copyFile( File from, File to ) throws IOException {
Files.copy( from.toPath(), to.toPath() );
}
很时髦,是吧?
要复制文件并将其保存到目标路径,您可以使用下面的方法。
public void copy(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
上述代码有三个可能的问题:
如果getChannel抛出异常,则可能泄漏一个开放流。 对于大文件,您可能会尝试一次传输超出操作系统处理能力的文件。 您忽略了transferFrom的返回值,因此它可能只是复制文件的一部分。
这就是为什么org.apache.tools.ant.util.ResourceUtils.copyResource如此复杂。还要注意,虽然transferFrom没问题,但transferTo会在Linux上的JDK 1.4上中断(参见Bug ID:5056395)
这里有三种方法,您可以轻松地复制文件与一行代码!
Java7:
java.nio.file.Files #副本
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
公共汽车共享10:
文件实用程序#复制文件
private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}
番石榴:
文件#复制
private static void copyFileUsingGuava(File source,File dest) throws IOException{
Files.copy(source,dest);
}
我会避免使用像apache commons这样的mega api。这是一个简单的操作,它内置于新的NIO包中的JDK中。在之前的回答中已经链接到它,但是NIO api中的关键方法是新函数“transferTo”和“transferFrom”。
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html transferTo(长,长% 20,% 20 java.nio.channels.writablebytechannel)
其中一篇链接的文章展示了如何使用transferFrom将这个函数集成到你的代码中:
public static void copyFile(File sourceFile, File destFile) throws IOException {
if(!destFile.exists()) {
destFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally {
if(source != null) {
source.close();
}
if(destination != null) {
destination.close();
}
}
}
学习NIO可能有点棘手,所以在尝试一夜之间学习NIO之前,您可能想要相信这个机制。从个人经验来看,如果你没有经验,并且是通过java介绍到IO的,那么学习它可能是一件非常困难的事情。io流。