Runtime.exec的使用注意

最近做项目时,发现Linux下保存附件文件的时候采用的是原来的附件名称命名,因字符集的原因导致中文乱码,下载文件时获取不到文件。

Linux 系统的默认编码是 UTF-8,JAVA 系统的环境编码 file.encoding  是GBK,保存附件文件的时候没有进行任何的转码处理,可能因此导致了文件乱码,当然具体乱码的原因也就不再深究了。乱码文件名的附件无法下载,所以只能重命名了。

一开始想使用的是 renameTo,sourceFile.renameTo(destFile),但是发现虽然 listFiles() 可以列出文件夹下的文件数量, 但是想通过 listFiles() 去获取具体的文件时任然因乱码获取不到具体的文件。

还好当初保存文件时,都是一个文件夹 保存一个文件的。就只能使用 Runtime.getRuntime().exec(cmd) 来重命名文件了。所以就将Runtime.getRuntime().exec(cmd) 学习了一下,此处保留下当时使用的一些代码:

修改文件时的路径需要填写绝对路径,并且 Linux 下使用 "/" ,Windows 下使用 "\",当初使用 File.separator 出现了异常,所以我都是直接使用字符的。

 if (isWindows) {
     execCmd(parentFile.getName(), childFile[0].getName(), nameMap.get(parentFile.getName()), "cmd /c ren " + cmd.toString().replace("/", "\\"), true);
} else {
     execCmd(parentFile.getName(), childFile[0].getName(), nameMap.get(parentFile.getName()), "mv " + cmd.toString().replace("\\", "/"), false);
}

	
    /**
     * 执行命令行
     * 
     * @param parentPath
     * @param sorFileName
     * @param tarFileName
     * @param cmd
     * @param isWindows
     */
    private void execCmd(String parentPath, String sorFileName, String tarFileName, String cmd, boolean isWindows) {
        try {
            System.err.println(cmd.toString());
            Process process = null;
            if (isWindows) {
                process = Runtime.getRuntime().exec(cmd);
            } else {
                // exec 只接受GBK的命令,其他的命令为乱码
                String[] cmds = { "/bin/sh", "-c", new String(cmd.getBytes("UTF-8"), "GBK") };
                process = Runtime.getRuntime().exec(cmds);
            }

            // any error message?
            StreamGobbler err = new StreamGobbler(process.getErrorStream());
            // any output?
            StreamGobbler out = new StreamGobbler(process.getInputStream());
            err.start();
            out.start();
            process.waitFor();
        
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   }
外部程序开始执行的时候必须马上控制输入、输出、出错这些流,所以采用多线程的方式输出这些流
class StreamGobbler extends Thread {
    InputStream is;

    StreamGobbler(InputStream is) {
        this.is = is;
    }

    public void run() {
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            String line = null;
            StringBuffer infoMsg = new StringBuffer();
            while ((line = br.readLine()) != null) {
                infoMsg.append(line).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (isr != null) {
                    isr.close();
                }
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

总结了几条规则,防止我们在进行Runtime.exec()调用时出现错误。
    修改文件时的路径需要填写绝对路径,并且 Linux 下使用 "/" ,Windows 下使用 "\",当初使用 File.separator 出现了异常,所以我都是直接使用字符的。
    在一个外部进程执行完之前你不能得到他的退出状态
    在你的外部程序开始执行的时候你必须马上控制输入、输出、出错这些流。
    你必须用Runtime.exec()去执行程序
    你不能象命令行一样使用Runtime.exec()。

参考文章:http://jiangshuiy.iteye.com/blog/1674235


你可能感兴趣的:(工作学习)