Windows xcopy using java Runtime.exec not working for filenames with chinese characters
Asked Answered
H

3

2

I currently have a java program that uses xcopy with Runtime.exec to copy files. But the problem now is that when the file name has chinese characters this does not work. It gives a file not found error. However if i copy the file path from explorer and do xcopy from the command line copy works. I am executing it from a Windows 7 machine. Any solutions will be much appreciated.

Thanks

This is related to the bug https://bugs.java.com/bugdatabase/view_bug?bug_id=4947220. Instead of passing the parameters as arguments, passed them via environment variables which worked perfectly.

Haemostasis answered 23/12, 2011 at 21:54 Comment(2)
Did you try ProcessBuilder instead? It is supposed to be better than Runime.exec()Fimbriation
Tried this too..but in vain...Haemostasis
T
5

Why are you using xcopy? Use java.

Try to do it with java.nio.file.Files

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

Files.copy(a,b);

See here for doc:

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...)

Tamarisk answered 23/12, 2011 at 22:9 Comment(0)
M
2

The exec in Java converts the strings to the system code page. Shameful, for the XXI century, but that's how it is.

But Java is not the only bottleneck here. The console is also problematic, and xcopy might have it's own share.

There is a lot of voodoo that you can try, for instance starting cmd.exe as Unicode (/U), and/or setting the code page to utf-8 (chcp 65001), or create a batch file with the command and call that batch (so no high-ascii in the exec function). But I would not relay on that.

Since everything is Windows only anyway, I would probably try using jni to implement a "proper" exec, or see if FileCopy is faster than the Java copy.

Motherwort answered 28/12, 2011 at 11:29 Comment(0)
E
1

If you need to copy large files, or files and all the system permissions associated with a file, using java internal File.copy() will be too expensive, so you can offload all the load to your system.

Try the following trick - first, user string array as an argument to exec(); second, execute your 'xcopy' in a pipe after 'cmd' command with /C argument. Look at the sample code near line where I make isWindows() call.

The trick is that your xcopy command will be executed inside CMD shell, and /C will terminate it after successful execution. More aboutCMD.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;
}
Eteocles answered 23/12, 2011 at 21:54 Comment(5)
Seego.Thanks for the reply. But this too does not work when i change to xcopy. It gives me file not foundHaemostasis
print out the copyCommand array on the console and check if command is created correctlyEteocles
This is how my command looks like cmd = new String[]{"cmd", "/C", "xcopy", "/R", "/C", "/Y","/S", source.getAbsolutePath(), destPath.getCanonicalPath()};Haemostasis
I meant to see the command right before Runtime.getRuntime().exec(). It is important to see what file paths you are feeding into the command, and it looks like getCanonicalPath() may not be a valid filesystem path.Eteocles
This is what the command looks like cmd /C xcopy /R /C /Y /S c:\????.zip c:\test. The output says ????.zip not found.Haemostasis

© 2022 - 2024 — McMap. All rights reserved.