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

在Java中使用cmd复制文件时出现问题,java,windows,command-line,process,runtime,Java,Windows,Command Line,Process,Runtime,我正在尝试使用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 = cop

我正在尝试使用
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个文件),则会停止响应!!而且文件也不会被复制!!
我不知道是什么问题,如果有人能帮忙,我会很高兴的!:)

您没有读取
copy
命令生成的输出

使用ProcessBuilder生成子进程时,子进程生成的输出将写入缓冲区。如果不从中读取此缓冲区,它最终会被填满。当它填满时,
copy
命令无法再写入,因此被操作系统阻止。然后,它被迫等待,直到通过读取缓冲区中的数据在缓冲区中产生空间

我用20个文件运行了你的代码,发现它确实挂起了

解决问题的一种方法是将输出从
copy
重定向到
NUL
copy
的大部分输出都是它复制的所有文件的列表,您可能不太关心这些文件。要执行此重定向,请将分配给
命令[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个文件对每种方法进行了快速测试,两种方法都没有挂起


编辑:您可能还想尝试一种“混合”方法,即扔掉
复制
写入标准输出的内容(例如,复制的文件列表),但使用第二种方法读取写入标准错误的内容(例如,错误消息)。为此,您需要添加
>NUL
,它将
copy
的标准输出重定向到
NUL
,但您不需要添加
2>NUL
,由于这会将标准错误重定向到
NUL

,因此从该目录中包含超过15个txt文件的命令窗口运行该命令是否会导致其停止响应?还是只有在从JVM调用命令时才会发生这种情况?@keepitreall89,在命令窗口中,它工作正常!只有jvm才有可能。一个可能的解决方案是在命令[2]字符串中的“C:\\output\\”之后添加/Y标志,这将防止它试图询问您是否要覆盖具有相同名称的文件。问题可能是一个同名文件已经存在,因此它会询问您是否要覆盖它,只有您的java调用不会“侦听”该文件。您是否有理由需要从cmd执行此操作,或者只使用java复制文件也是可以接受的?@keepitreal89:我运行OP的代码时没有
p.waitFor()
行。这消除了挂起的问题,但我发现没有复制任何文件。伍德沃德,非常感谢,我接受这一回答,我实际上在尝试这种缓冲读取器方法,我理解第二种方法,但在第一种方法中,为什么会重定向两次?有什么意义吗??)@Hari:所有进程都有一个标准输出和一个用于写入的标准错误流,请参阅。使用
>NUL
2>NUL
将标准输出和标准错误流重定向到
NUL
。你不能同时重定向它们。当然,如果
copy
向其标准错误流写入了大量内容,而您没有读取其标准错误,则它将挂起。