为什么不';Java执行Windows批处理文件时,我的Windows批处理文件不会处理吗?

为什么不';Java执行Windows批处理文件时,我的Windows批处理文件不会处理吗?,java,windows,batch-file,cmd,Java,Windows,Batch File,Cmd,我有两个文件夹,每个文件夹包含几十个批处理文件(*.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\IMAGE

我有两个文件夹,每个文件夹包含几十个批处理文件(
*.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

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

公共静态布尔批处理(文件){
布尔值=假;
Process=null;
试一试{
process=Runtime.getRuntime().exec(“cmd/c start”+文件);
handled=process.waitFor()==0;
}捕获(例外情况除外){
//出于示例目的,已删除处理
} 
处理退货;
}
方法返回后,我删除批处理文件

问题是,批处理文件中的任何命令都不会运行(我请求删除或删除的文件和文件夹不会运行),Java过程只是继续并删除批处理文件本身

批处理文件位于文件夹
d:\working\spaced folder\purge\batch\u files\

写出来之后,我怀疑我的问题是我正在将一个带有空格的文件路径传递给
exec()
方法

我的怀疑正确吗?如果是,我如何解决它?如果不是,问题可能是什么

既然我已经考虑过了,我现在就要调查一下


更新 根据下面的注释,我已经更改了代码,但是现在输出挂起在
waitFor()
,批处理文件没有被处理(我请求删除的文件仍然存在)

代码:

String commandString=“cmd/c\”+文件+“\”;
logger.info(“命令”+命令字符串);
process=Runtime.getRuntime().exec(commandString);
logger.info(“等待”+commandString);
handled=process.waitFor()==0;
logger.info(“已处理”+命令字符串+“=”+已处理);
输出:

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"
现在输出挂起在
waitFor()

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

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

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

ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.getAbsolutePath());
根据Ian Roberts的回答,使用的成功解决方案代码: 使用


如果批处理文件路径中有一个空格,那么是的,您将执行
del c:\foo bar
,而此时它应该是
del“c:\foo bar”
。在
文件
参数周围加上引号您可能不想使用
启动
命令,因为如果这样做,调用
.waitFor
将不会等待批处理文件完成。加引号的速度似乎较慢,但我没有看到从内部批处理调用中删除任何文件。我将尝试不使用
start
,因为我认为这可能是问题所在。我最初没有
开始
,但这就是我首先阅读StackOverflow获得答案的原因:PNo,现在它只是挂起处理文件。不知道会走多远;添加debug.No。通过cmd.exe删除目录的速度要比在Java中快很多倍。Windows有一个通配符删除系统调用:Java没有@OP我将从命令中删除“开始”。你想知道它是否有效,如果你使用“开始”,你就不会知道。我现在就试试,谢谢。仅供参考,
ProcessBuilder pb=newprocessbuilder(“cmd”,“/c”,file.toString())
@JoshDM如果它是
java.io.File
那么
getAbsolutePath
toString
更安全,因为它将为您提供完整的路径,即使
文件本身是相对的。谢谢。这帮助我解决了这个问题。核对答案;使用的解决方案代码在单独的答案中公布。
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.getAbsolutePath());
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;
    }
}