Java 调用 CMD 命令时路径名带空格的解决方案

背景

当我们在终端执行命令行时,如果遇到带空格的路径名,往往有两种处理方法

cat a\ b\ c.txt
测试内容

cat 'a b c.txt'
测试内容

而当我们在Java使用 Runtime.getRuntime().exec() 执行上面的命令时,却得不到想要的结果

分析

想要解决该问题,首先分析 exec(String cmd) 方法的源码

public Process exec(String command, String[] envp, File dir)
    throws IOException {
    if (command.length() == 0)
        throw new IllegalArgumentException("Empty command");

    StringTokenizer st = new StringTokenizer(command);
    String[] cmdarray = new String[st.countTokens()];
    for (int i = 0; st.hasMoreTokens(); i++)
        cmdarray[i] = st.nextToken();
    return exec(cmdarray, envp, dir);
}
public StringTokenizer(String str) {
    this(str, " \t\n\r\f", false);
}

public StringTokenizer(String str, String delim, boolean returnDelims) {
    currentPosition = 0;
    newPosition = -1;
    delimsChanged = false;
    this.str = str;
    maxPosition = str.length();
    delimiters = delim;
    retDelims = returnDelims;
    setMaxDelimCodePoint();
}

可以看到,首先会将CMD命令构造成一个 StringTokenizer 对象,该对象的默认分隔符是" \t\n\r\f", 也就是常见的空格符、换行符、制表符。也就是说,只要命令出现了这些符号,不管有没有带上转移或者引号,都会被分割成 cmdarry ,流入后面的方法exec(String[] cmdarray)

解决方案

其实到这一步我们已经知道该怎么解决了,我们肯定不能修改它默认的分隔符,因为这样的话 所有的空格都将不会被分割。所以我们只能跳过源码分割阶段,自己分割CMD命令,然后直接将cmdarray传给exec(String[] cmdarray)方法 。代码如下,注意前两行代码:

String[] cmdarray = new String[]{"cat", "/Users/ciel/Downloads/a b c.txt"};
Process process = Runtime.getRuntime().exec(cmdarray);
InputStream in = process.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
BufferedReader br = new BufferedReader(reader);
StringBuffer sb = new StringBuffer();
String message;
while ((message = br.readLine()) != null) {
    sb.append(message);
}
System.out.println(sb);

// 得到文件的内容:
// 测试内容

参考资料


文章标题:Java 调用 CMD 命令时路径名带空格的解决方案
文章作者:Ciel Ni
文章链接:http://www.cielni.com/2021/07/24/java-cmd/
有问题或建议欢迎与我联系讨论,转载或引用希望标明出处,感激不尽!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容