2

我目前有一个使用 xcopy 和 Runtime.exec 来复制文件的 java 程序。但现在的问题是,当文件名有中文字符时,这不起作用。它给出了一个找不到文件的错误。但是,如果我从资源管理器复制文件路径并从命令行复制工作 xcopy 。我正在从 Windows 7 机器上执行它。任何解决方案将不胜感激。

谢谢

这与错误http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4947220有关。不是将参数作为参数传递,而是通过完美运行的环境变量传递它们。

4

3 回答 3

5

你为什么使用xcopy?使用java。

尝试用 java.nio.file.Files 来做

Path a = ...
Path b = ...

Files.copy(a,b);

请参阅此处获取文档:

http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#copy(java.nio.file.Path,%20java.nio.file.Path,%20java. nio.file.CopyOption...)

于 2011-12-23T22:09:38.740 回答
2

Java 中的 exec 将字符串转换为系统代码页。可耻的是,对于二十一世纪,但事实就是如此。

但 Java 并不是这里唯一的瓶颈。控制台也有问题,xcopy 可能有它自己的份额。

您可以尝试很多巫术,例如将 cmd.exe 启动为 Unicode (/U),和/或将代码页设置为 utf-8 (chcp 65001),或者使用命令创建批处理文件并调用该批次(因此 exec 函数中没有高 ascii)。但我不会转述这一点。

由于无论如何一切都是Windows,我可能会尝试使用jni来实现“正确”的执行,或者看看FileCopy是否比Java副本快。

于 2011-12-28T11:29:49.707 回答
1

如果您需要复制大文件,或文件以及与文件关联的所有系统权限,使用 java internal File.copy() 将过于昂贵,因此您可以将所有负载卸载到系统上。

尝试以下技巧 - 首先,将用户字符串数组作为 exec() 的参数;其次,在带有 /C 参数的“cmd”命令之后在管道中执行“xcopy”。查看我进行 isWindows() 调用的行附近的示例代码。

诀窍是您的 xcopy 命令将在 CMD shell 中执行,而 /C 将在成功执行后终止它。更多关于CMD.exe的信息。

public int sysCopyFile(Resource fromResource, Resource toResource) throws ServiceException {
    int returnCode = -1;
    try {
        String[] copyCommand = null;

        if ( IOUtils.isWindows() ) {
            copyCommand = new String[] {"cmd", "/C", "copy", "/Y", fromResource.getFile().getAbsolutePath(), toResource.getFile().getAbsolutePath()};
        } else if ( IOUtils.isUnix() || IOUtils.isMac() ) {
            copyCommand = new String[] {"/bin/cp", "-pr", fromResource.getFile().getAbsolutePath(),toResource.getFile().getAbsolutePath()};
        }

        final Process p = Runtime.getRuntime().exec(copyCommand);
        new StreamLogger(p.getErrorStream(), log, StreamLogger.WARN);
        new StreamLogger(p.getInputStream(), log, StreamLogger.DEBUG);

        returnCode = p.waitFor();

        if (returnCode != 0) throw new ServiceException("Unable to to copy. Command: {" + copyCommand[0] + "} has returned non-zero returnCode: " + returnCode);
    } catch (IOException e) {
        throw new ServiceException(e);  
    } catch (InterruptedException e) {
        throw new ServiceException(e);
    }
    return returnCode;
}
于 2011-12-23T22:14:37.563 回答