我们有一个Java程序,需要在中间进程中对文件进行排序。有问题的文件可能包含键盘可用的任何可打印字符。我们能够在标准的单字符分隔符上执行排序OK,但是当排序遇到该字符时,它会错误地解析。我们希望使用制表符分隔符或多字符分隔符,以便无论数据的内容如何,文件都可以正确排序。我们正在动态构建命令字符串并将其传递给shell来执行,如下所示。
execStr = new StringBuffer("/usr/bin/sort -n +1n -2 +0n -1 -o " + outputFile.toString() + " -t " + DELIMITER + " " + outputFile.toString());
Process runProc = Runtime.getRuntime().exec (execStr.toString());
如果我们包含$和tick标记来包装分隔符,则排序无法在第一列上找到所需的列和排序,这使我们在将标签字符指定为$'\t'
时出现问题。我们尝试使用可打印范围之外的字符,例如$'Ç'
(十六进制C7),但排序机制Java字符串为$'?'
等字符发布问号,这当然对我们不起作用。看起来像Java处理字符串的方式以及 sort 如何读取它们的方式让我们适合。有没有其他人遇到过这个问题,如果有的话,你是怎么解决的?理想情况下,使用多字符分隔符对我们来说是最好的,但如果我们能够使用它,我们将使用tab char。
提前致谢, 麦克
答案 0 :(得分:1)
使用便捷方法让你自己变得困难!
首先,$'\t'
是什么?这是四个字符,而不是指定制表符的任何方式。
关键是要注意,在exec(command)
中,command
字符串使用StringTokenizer进行拆分,StringTokenizer将在空格上拆分命令字符串。空格包含您的制表符,因此消失 - 这是为什么包含文字制表符不起作用。
另外(虽然这与你的问题没有任何关系),你的StringBuffer是多余的,因为它是用一个字符串初始化的,它使用+
通常的方式连接。
您最好使用ProcessBuilder创建命令(如建议的jackrabbit评论)。这样,你可以准确地控制哪些参数是什么,如果你包含一个文字制表符作为参数之一,那么它将包含在传递给程序的参数中。
ProcessBuilder pb = new ProcessBuilder("/usr/bin/sort", "-t", "\t", ...);
在执行类似这样的操作时,很容易犯错误,忘记shell在终端中键入的命令上做了很多工作,并且没有shell执行那种转义在这样的环境中工作。 shell汇集了一个由字符串数组组成的参数列表,这就是传递给exec(3)的内容。为了理智,你想尽可能地跳过中间人,并自己组装这个字符串。