为什么Java执行时我的Windows批处理文件不能处理?

时间:2014-01-27 21:45:12

标签: java windows batch-file cmd

我有2个文件夹,每个文件夹包含数十个批处理文件(*.bat)。

包含类似于

的文本的批处理文件
del /f/q F:\MEDIA\IMAGE99\2010\270\z\4034\123.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\266\z\3025\456.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\267\z\3025\789.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\286\z\9025\101.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\272\z\6029\112.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\258\z\4034\134.tif > nul

rmdir /q F:\MEDIA\IMAGE99\2010\270\z\4034
rmdir /q F:\MEDIA\IMAGE99\2010\266\z\3025
rmdir /q F:\MEDIA\IMAGE99\2010\267\z\3025
rmdir /q F:\MEDIA\IMAGE99\2010\286\z\9025
rmdir /q F:\MEDIA\IMAGE99\2010\272\z\6029
rmdir /q F:\MEDIA\IMAGE99\2010\258\z\4034

在Java中,我列出了每个文件夹中的每个批处理File,并在列表中循环,执行每个批处理文件,如下所示:

public static boolean batch(File file) {

    boolean handled = false;
    Process process = null;
    try {

        process = Runtime.getRuntime().exec("cmd /c start " + file);
        handled = process.waitFor() == 0;

    } catch (Exception ex) {
        // handling removed for example purposes
    } 

    return handled;
}

方法返回后,我删除了批处理文件。

问题是,我的批处理文件中没有命令运行(我请求删除或删除的文件和文件夹不是),Java进程只是继续并删除批处理文件本身。

批处理文件位于文件夹d:\working\spaced folder\purge\batch_files\

写完之后,我怀疑我的问题是我将带有空格的文件路径传递给exec()方法。

我的怀疑是否正确?如果是这样,我该如何解决?如果没有,问题可能是什么?

我现在要考虑Java: Execute /cmd /c start path-with-spaces\program.exe,我已经考虑过了。


更新

根据下面的评论,我已经更改了我的代码,但现在输出挂起在waitFor()并且批处理文件没有被处理(我请求删除的文件仍在那里)。

代码:

        String commandString = "cmd /c \"" + file +"\"";
        logger.info("COMMAND " + commandString);
        process = Runtime.getRuntime().exec(commandString);
        logger.info("WAITING FOR " + commandString);
        handled = process.waitFor() == 0;
        logger.info("HANDLED " + commandString + " = " + handled);

输出:

COMMAND : cmd /c "d:\working\spaced folder\purge\deleteBatch\F_140.bat"
WAITING FOR : cmd /c "d:\working\spaced folder\purge\deleteBatch\F_140.bat"

2 个答案:

答案 0 :(得分:3)

  

现在输出挂起waitFor()

使用Runtime.exec从Java启动外部进程时,必须读取进程生成的任何输出,否则进程可能会阻塞(source: JavaDocs for java.lang.Process)。

改为使用ProcessBuilder,并调用redirectErrorStream合并标准输出和错误流,然后从process.getInputStream()读取所有内容,直到达到EOF。只有这样才能安全地拨打waitFor

ProcessBuilder还将帮助解决空间问题,因为您必须自己将命令行拆分为单个单词

ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.getAbsolutePath());

答案 1 :(得分:0)

使用成功解决方案的代码,基于Ian Roberts的回答:

使用Apache Commons-IO

package com.stackoverflow.windows;

import java.io.File;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;

public class Command {

    private Command() {}

    public static boolean batch(File file) {

        boolean handled = false;
        Process process = null;
        ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.getAbsolutePath());
        pb.redirectErrorStream(true);

        try {

            process = pb.start();
            IOUtils.copy(process.getInputStream(), new NullOutputStream());
            handled = process.waitFor() == 0;

        } catch (Exception ignore) {

            // Only throws an IOException we're trying to avoid anyway, 
            // and an expected InterruptedException 
            // handled will be false

        } finally {

            if (process != null) {

                IOUtils.closeQuietly(process.getInputStream());
            }           
        }

        return handled;
    }
}