使用Java中的cmd复制文件时出现问题

5

我正在尝试使用copy命令将一个文件夹中特定扩展名的一堆文件复制到另一个文件夹,以下是我的操作:

 String[] command = new String[3];
 command[0] = "cmd";
 command[1] = "/c";
 command[2] = "copy C:\\output\\html\\*.txt C:\\output\\";

 ProcessBuilder copyFiles = new ProcessBuilder(command);
 p = copyFiles.start();
 p.waitFor();

问题是,这段代码对于少于5个左右的文件可以正常工作,但是当文件数量增多时(即使只有15个文件),它就会停止响应!!而且文件也没有被复制!!我不知道问题出在哪里,如果有人能帮忙就太好了!:)


1
在具有超过15个txt文件的目录中从命令窗口运行该命令会导致它停止响应吗?还是只有在从JVM调用命令时才会发生这种情况? - keepitreall89
1
一个可能的解决方案是在你的命令[2]字符串中添加/Y标志,紧跟在"C:\output\"之后,这将防止它尝试询问您是否要覆盖同名文件。问题可能是已经存在一个具有该名称的文件,因此它会询问您是否要覆盖它,只是您的Java调用没有“听到”它。 - keepitreall89
1
你需要从命令行执行这个操作吗?还是直接使用Java复制文件也可以接受? - keepitreall89
1
@keepitreal89:我运行了OP的代码,但没有加上p.waitFor()这一行。这样可以解决卡住的问题,但是我发现没有文件被复制。 - Luke Woodward
是的,Luke说得对,如果我们不等待它完成,文件就不会被复制(至少不是所有文件) :) - Hari Krishna
显示剩余3条评论
1个回答

6
您没有读取copy命令生成的输出。
使用ProcessBuilder生成子进程时,您的子进程生成的输出会被写入缓冲区。如果不从中读取该缓冲区,它最终会填满。当它填满时,copy命令无法再向其中写入内容,因此被操作系统阻塞。然后,它被迫等待通过从中读取来释放缓冲区中的空间。
我运行了您的代码并复制了20个文件,发现它确实挂起了。
解决问题的一种方法是将copy的输出重定向到NUL。大多数copy的输出是它已复制的所有文件的列表,您可能不太关心这些内容。要执行此重定向,请修改分配给command[2]的行如下:
command[2] = "copy C:\\output\\html\\*.txt C:\\output\\ >NUL 2>NUL";

然而,如果复制文件出现问题,如果你这样做的话可能不会知道。或者,你可以阅读copy命令生成的输出。以下代码将其发送到System.out,但是如果您希望,可以轻松地将其发送到其他地方或完全忽略它:
String[] command = { "cmd", "/c", "copy C:\\output\\html\\*.txt C:\\output\\" };
ProcessBuilder copyFiles = new ProcessBuilder(command);
copyFiles.redirectErrorStream(true);
p = copyFiles.start();

// The InputStream we get from the Process reads from the standard output
// of the process (and also the standard error, by virtue of the line
// copyFiles.redirectErrorStream(true) ).
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
do {
    line = reader.readLine();
    if (line != null) { System.out.println(line); }
} while (line != null);
reader.close();

p.waitFor();

我用同样的20个文件对每种方法进行了快速测试,两种方法都没有卡住。
编辑:您还可以尝试“混合”方法,即丢弃copy写入标准输出的内容(例如它正在复制的文件列表),但使用第二种方法读取它写入标准错误的内容(例如错误消息)。为此,您需要添加>NUL,将copy的标准输出重定向到NUL,但不需要添加2>NUL,因为这会将标准错误重定向到NUL

woodward,非常感谢,我接受这个答案了。我实际上正在尝试使用缓冲读取器方法,并且我理解了第二种方法,但是在第一种方法中,为什么要重定向两次?有任何特殊意义吗? :) - Hari Krishna

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