Проблема с копированием файлов с использованием cmd в Java - PullRequest
5 голосов
/ 02 мая 2011

Я пытаюсь скопировать группу файлов с определенным расширением из одной папки в другую с помощью команды 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 Ответ

6 голосов
/ 02 мая 2011

Вы не читаете вывод, который генерирует команда 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.

...