在Java中复制文件并替换现有目标

52

我正在尝试使用java.nio.file.Files复制文件,类似于以下代码:

Files.copy(cfgFilePath, strTarget, StandardCopyOption.REPLACE_EXISTING);

问题在于Eclipse提示"The method copy(Path, Path, CopyOption...) in the type Files is not applicable for the arguments (File, String, StandardCopyOption)"

我正在使用Eclipse和Java 7,在Win7 x64上。我的项目设置为使用Java 1.6兼容性。

是否有解决方法,还是我必须创建类似以下的解决方法:

File temp = new File(target);

if(temp.exists())
  temp.delete();

谢谢。

5个回答

129

您需要按照错误信息所述传递Path参数:

Path from = cfgFilePath.toPath(); //convert from File to Path
Path to = Paths.get(strTarget); //convert from String to Path
Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);

假设您的strTarget是一个有效的路径。


啊,为什么我认为这是与copyOption有关的问题呢...完全忽略了前两个参数类型,谢谢提醒。看来我在高温下编码时间太长了。;-) - commander_keen
哎呀,将导出的jar文件复制到安装了Java 1.6的电脑上后(这就是我提到需要兼容1.6的原因,尽管我使用Java 7进行开发并编译为1.6),它抱怨说“Exception in thread "main" java.lang.NoSuchMethodError: java.io.File.toPath()Lja va/nio/file/Path;”,根据文档,这是正确的,因为此方法仅在Java 7及以上版本中可用。(我想知道为什么在开发/设计时没有像我之前尝试使用Java 7的其他功能一样受到批评,现在我必须手动检查所有内容...) - commander_keen
我有一个关于这个的问题:如果两个人上传了一个名称和类型相同但是内容不同的图片,那么最后上传相同类型的人将替换之前的图片。对于这个问题我该怎么办呢?因为类型和名称相同但是内容不同,所以我不想替换它。 - Vikas Roy
@VikasRoy 我建议您提出一个单独的问题,解释您的具体问题。 - assylias

10

作为 @assylias 回答的补充:

如果你使用的是Java 7,那么完全可以放弃使用File。你需要的是Path

要获取与文件系统上路径相匹配的Path对象,你可以这样做:

Paths.get("path/to/file"); // argument may also be absolute

要尽快适应它。请注意,如果您仍在使用需要 File 的 API,则 Path 有一个 .toFile() 方法。

请注意,如果您不幸使用返回 File 对象的 API,则始终可以执行以下操作:

theFileObject.toPath()

但在你的代码中,请系统地使用 Path。不要犹豫。

编辑 使用1.6版本的NIO将文件复制到另一个文件可以这样做;请注意,Closer类受到Guava的启发:

public final class Closer
    implements Closeable
{
    private final List<Closeable> closeables = new ArrayList<Closeable>();

    // @Nullable is a JSR 305 annotation
    public <T extends Closeable> T add(@Nullable final T closeable)
    {
        closeables.add(closeable);
        return closeable;
    }

    public void closeQuietly()
    {
        try {
            close();
        } catch (IOException ignored) {
        }
    }

    @Override
    public void close()
        throws IOException
    {
        IOException toThrow = null;
        final List<Closeable> l = new ArrayList<Closeable>(closeables);
        Collections.reverse(l);

        for (final Closeable closeable: l) {
            if (closeable == null)
                continue;
            try {
                closeable.close();
            } catch (IOException e) {
                if (toThrow == null)
                    toThrow = e;
            }
        }

        if (toThrow != null)
            throw toThrow;
    }
}

// Copy one file to another using NIO
public static void doCopy(final File source, final File destination)
    throws IOException
{
    final Closer closer = new Closer();
    final RandomAccessFile src, dst;
    final FileChannel in, out;

    try {
        src = closer.add(new RandomAccessFile(source.getCanonicalFile(), "r");
        dst = closer.add(new RandomAccessFile(destination.getCanonicalFile(), "rw");
        in = closer.add(src.getChannel());
        out = closer.add(dst.getChannel());
        in.transferTo(0L, in.size(), out);
        out.force(false);
    } finally {
        closer.close();
    }
}

我想知道如果我按照所述的Java 1.6兼容级别进行编译是否能够成功,但无论如何感谢您的提示,将会记住它以备将来之需。 - commander_keen
@commander_keen 你的意思是你将部署到运行1.6 JVM的代码吗? - fge
这是正确的。正如上面评论中所认识到的,整个路径和复制方法都不起作用。 :-( 必须想办法只使用Java 1.6方法来复制文件并再次实现它。欢迎提供有关1.6最佳实践的提示。 - commander_keen
2
文件 != 文件。 Files是nio的一部分。请不要写60行样板代码来避免使用Files.copy。 - suriv
@suriv,原帖中说他必须使用Java 6...是的,我知道JSR 203。事实上非常了解。 - fge

7
package main.java;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class CopyFileOnExist {

    public static void main(String[] args)  {

        Path sourceDirectory = Paths.get("C:/Users/abc/Downloads/FileNotFoundExceptionExample/append.txt");
        Path targetDirectory = Paths.get("C:/Users/abc/Downloads/FileNotFoundExceptionExample/append5.txt");

        //copy source to target using Files Class
        try {
            Files.copy(sourceDirectory, targetDirectory,StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }

}

1

strTarget 是一个 "String" 对象而不是一个 "Path" 对象


0

你的语句Files.copy(path,String或者address,StandardCopyOption)是错误的,因为你传递的是一个字符串而不是保存文件的路径。

应该使用以下语句:

Files.copy(path,Paths.get(String 或 address),StandardCopyOption)

通过使用Paths.get方法将字符串转换为文件位置或路径,从而可以指定源文件路径以及要保存文件的位置。


1
目前来看,你的回答不够清晰。请编辑以添加更多细节,帮助其他人理解这如何回答所提出的问题。你可以在帮助中心找到关于如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接