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();
}
}
5
这些方法是性能设计的(它们与操作系统本机I / O集成) .
这些方法适用于文件,目录和链接 .
提供的每个选项都可以省略 - 它们是可选的 .
实用程序类
package com.yourcompany.nio;
class Files {
static int copyRecursive(Path source, Path target, boolean prompt, CopyOptions options...) {
CopyVisitor copyVisitor = new CopyVisitor(source, target, options).copy();
EnumSet<FileVisitOption> fileVisitOpts;
if (Arrays.toList(options).contains(java.nio.file.LinkOption.NOFOLLOW_LINKS) {
fileVisitOpts = EnumSet.noneOf(FileVisitOption.class)
} else {
fileVisitOpts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
}
Files.walkFileTree(source[i], fileVisitOpts, Integer.MAX_VALUE, copyVisitor);
}
private class CopyVisitor implements FileVisitor<Path> {
final Path source;
final Path target;
final CopyOptions[] options;
CopyVisitor(Path source, Path target, CopyOptions options...) {
this.source = source; this.target = target; this.options = options;
};
@Override
FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
// before visiting entries in a directory we copy the directory
// (okay if directory already exists).
Path newdir = target.resolve(source.relativize(dir));
try {
Files.copy(dir, newdir, options);
} catch (FileAlreadyExistsException x) {
// ignore
} catch (IOException x) {
System.err.format("Unable to create: %s: %s%n", newdir, x);
return SKIP_SUBTREE;
}
return CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
Path newfile= target.resolve(source.relativize(file));
try {
Files.copy(file, newfile, options);
} catch (IOException x) {
System.err.format("Unable to copy: %s: %s%n", source, x);
}
return CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
// fix up modification time of directory when done
if (exc == null && Arrays.toList(options).contains(COPY_ATTRIBUTES)) {
Path newdir = target.resolve(source.relativize(dir));
try {
FileTime time = Files.getLastModifiedTime(dir);
Files.setLastModifiedTime(newdir, time);
} catch (IOException x) {
System.err.format("Unable to copy all attributes to: %s: %s%n", newdir, x);
}
}
return CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
if (exc instanceof FileSystemLoopException) {
System.err.println("cycle detected: " + file);
} else {
System.err.format("Unable to copy: %s: %s%n", file, exc);
}
return CONTINUE;
}
}
复制目录或文件
long bytes = java.nio.file.Files.copy(
new java.io.File("<filepath1>").toPath(),
new java.io.File("<filepath2>").toPath(),
java.nio.file.StandardCopyOption.REPLACE_EXISTING,
java.nio.file.StandardCopyOption.COPY_ATTRIBUTES,
java.nio.file.LinkOption.NOFOLLOW_LINKS);
移动目录或文件
long bytes = java.nio.file.Files.move(
new java.io.File("<filepath1>").toPath(),
new java.io.File("<filepath2>").toPath(),
java.nio.file.StandardCopyOption.ATOMIC_MOVE,
java.nio.file.StandardCopyOption.REPLACE_EXISTING);
递归复制目录或文件
long bytes = com.yourcompany.nio.Files.copyRecursive(
new java.io.File("<filepath1>").toPath(),
new java.io.File("<filepath2>").toPath(),
java.nio.file.StandardCopyOption.REPLACE_EXISTING,
java.nio.file.StandardCopyOption.COPY_ATTRIBUTES
java.nio.file.LinkOption.NOFOLLOW_LINKS );
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();
}
}
}
21
我会避免使用像apache公共的mega api . 这是一个简单的操作,它内置于新的NIO包中的JDK中 . 它在之前的答案中已经有点联系了,但NIO api中的关键方法是新功能“transferTo”和“transferFrom” .
16 回答
现在使用Java 7,您可以使用以下try-with-resource语法:
或者,更好的是,这也可以使用Java 7中引入的新Files类来完成:
很时髦,嗯?
正如上面提到的工具包,Apache Commons IO是要走的路,特别是FileUtils . copyFile();它为您处理所有繁重的工作 .
并且作为附言,请注意最新版本的FileUtils(例如2.0.1版本)已经添加了使用NIO来复制文件; NIO can significantly increase file-copying performance,很大程度上是因为NIO例程将复制直接推迟到OS /文件系统而不是通过Java层读取和写入字节来处理它 . 因此,如果您正在寻找性能,可能需要检查您使用的是最新版本的FileUtils .
谷歌的Guava图书馆也有copy method:
Warning: 如果
to
表示现有文件,则该文件将被from
的内容覆盖 . 如果to
和from
引用同一文件,则将删除该文件的内容 .Parameters:
from
- 源文件to
- 目标文件Throws:
IOException
- 如果发生I / O错误IllegalArgumentException
- 如果from.equals(to)
在Java 7中很容易......
快速并使用Android的所有Java版本:
在Java 7中作为标准提供,path.copyTo:http://openjdk.java.net/projects/nio/javadoc/java/nio/file/Path.html http://java.sun.com/docs/books/tutorial/essential/io/copy.html
我无法相信它们花了这么长时间来标准化文件复制这么常见和简单的东西:(
如果您在已经使用Spring的Web应用程序中,并且如果您不想将Apache Commons IO包含在简单文件复制中,则可以使用Spring框架的FileCopyUtils .
要复制文件并将其保存到目标路径,您可以使用以下方法 .
这些方法是性能设计的(它们与操作系统本机I / O集成) .
这些方法适用于文件,目录和链接 .
提供的每个选项都可以省略 - 它们是可选的 .
实用程序类
复制目录或文件
移动目录或文件
递归复制目录或文件
上述代码有三个可能的问题:
如果getChannel抛出异常,您可能会泄漏打开的流 .
对于大文件,您可能尝试一次性传输比操作系统可以处理的更多文件 .
您忽略了transferFrom的返回值,因此它可能只是复制文件的一部分 .
这就是
org.apache.tools.ant.util.ResourceUtils.copyResource
如此复杂的原因 . 另请注意,虽然transferFrom正常,但是在Linux上的JDK 1.4上,transferTo会中断(参见Bug ID:5056395) - Jesse Glick Jan这里有三种方法可以轻松地使用单行代码复制文件!
Java7 :
java.nio.file.Files#copy
Appache Commons IO :
FileUtils#copyFile
Guava :
Files#copy
我会避免使用像apache公共的mega api . 这是一个简单的操作,它内置于新的NIO包中的JDK中 . 它在之前的答案中已经有点联系了,但NIO api中的关键方法是新功能“transferTo”和“transferFrom” .
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html#transferTo(long,%20long,%20java.nio.channels.WritableByteChannel)
其中一篇链接文章展示了如何使用transferFrom将此功能集成到代码中的一种很好的方法:
学习NIO可能有点棘手,所以你可能只想信任这个机制,然后再去尝试一夜之间学习NIO . 根据个人经验,如果您没有经验并且通过java.io流引入IO,那么学习起来可能会非常困难 .
请注意,所有这些机制仅复制文件的内容,而不复制权限等元数据 . 因此,如果您要在Linux上复制或移动可执行文件.sh文件,则新文件将无法执行 .
为了真正复制或移动文件,即获得与从命令行复制相同的结果,您实际上需要使用本机工具 . shell脚本或JNI .
显然,这可能会在java 7中修复 - http://today.java.net/pub/a/today/2008/07/03/jsr-203-new-file-apis.html . 手指交叉!
根据我的测试,使用缓冲区的NIO拷贝是最快的 . 请参阅我的测试项目下面的工作代码https://github.com/mhisoft/fastcopy
}
一个派对迟到了,但这里是使用各种文件复制方法复制文件所用时间的比较 . 我通过这些方法循环了10次并取平均值 . 使用IO流的文件传输似乎是最糟糕的候选者:
以下是方法:
我在使用NIO通道类时可以看到的唯一缺点是我仍然无法找到显示中间文件复制进度的方法 .