在Java程序中,我通过Process
生成一个新的ProcessBuilder
。
args[0] = directory.getAbsolutePath() + File.separator + program;
ProcessBuilder pb = new ProcessBuilder(args);
pb.directory(directory);
final Process process = pb.start();
然后,我使用新的Thread
new Thread() {
public void run() {
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}.start();
但是,当该过程输出非ASCII字符(例如'é'
)时,line
会改为字符'\uFFFD'
。
InputStream
返回的getInputStream
中的编码是什么(我的平台是欧洲的Windows)?
如何更改内容以使line
包含预期数据(即'\u00E9'
的{{1}})?
修改:我试过'é'
:
new InputStreamReader(...,"UTF-8")
变为é
答案 0 :(得分:9)
InputStream是二进制流,因此没有编码。创建Reader时,您需要知道要使用的字符编码,这取决于您调用的程序产生的内容(Java不会以任何方式转换它)。
如果没有为InputStreamReader指定任何内容,它将使用平台默认编码,这可能不合适。 another constructor允许您指定编码。
如果你知道要使用什么编码(你真的必须知道):
new InputStreamReader(process.getInputStream(), "UTF-8") // for example
答案 1 :(得分:5)
有趣的是,在Windows上运行时:
ProcessBuilder pb = new ProcessBuilder("cmd", "/c dir");
Process process = pb.start();
然后CP437代码页适用于
new InputStreamReader(process.getInputStream(), "CP437");
答案 2 :(得分:3)
据我所知,操作系统流是字节流,这里没有字符。 InputStreamReader
构造函数使用jvm默认字符集java.nio.charset.Charset#defaultCharset()
,您可以使用另一个构造函数来显式指定字符集。
答案 3 :(得分:2)
根据http://www.fileformat.info/info/unicode/char/e9/index.htm'\ uFFFD'是字符'é'的unicode代码。它实际上意味着您正在正确地读取流。你的问题是书面形式。
默认情况下,Windows控制台不支持unicode。所以,如果你想测试你的代码打开文件并在那里写你的流。但是不要忘记设置编码UTF-8
。
答案 4 :(得分:1)
在Windows上,这非常有效:
private static final Charset CONSOLE_ENCODING;
static {
Charset enc = Charset.defaultCharset();
try {
String example = "äöüßДŹす";
String command = File.separatorChar == '/' ? "echo " + example : "cmd.exe /c echo " + example;
Process exec = Runtime.getRuntime().exec(command);
InputStream inputStream = exec.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (exec.isAlive()) {
Thread.sleep(100);
}
byte[] buff = new byte[inputStream.available()];
if (buff.length > 0) {
int count = inputStream.read(buff);
baos.write(buff, 0, count);
}
byte[] array = baos.toByteArray();
for (Charset charset : Charset.availableCharsets().values()) {
String s = new String(array, charset);
if (s.equals(example)) {
enc = charset;
break;
}
}
} catch (InterruptedException e) {
throw new Error("Could not determine console charset.", e);
} catch (IOException e) {
throw new Error("Could not determine console charset.", e);
}
CONSOLE_ENCODING = enc;
}
根据规范:没有提示jvm的运行时编码更改。我们不能确保编码在运行时不会更改,并且在更改后字符集仍然正确。
答案 5 :(得分:1)
如果像我一样,如果您想对所有输入/输出使用哪种编码,则可以在对某些(并非全部)CreateReader方法的Java API调用中对它进行编码,其他一些答案也指出了这一点。
但这会在源代码中对其进行硬编码,这可能会也可能不会。
在阅读this answer之后,我发现了一种更好的方法,该方法表明您可以在JVM启动之前将编码设置为所需的值。
java -Dfile.encoding=ISO-8859-1 ...
答案 6 :(得分:0)
我把它作为评论,但我看到之后有一个答案,所以现在可能是多余的:)
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
答案 7 :(得分:0)
在此用途中使用commons-lang jar文件 - StringEscapeUtils.escapeHtml
BufferedReader br = new BufferedReader(
new InputStreamReader(StringEscapeUtils.escapeHtml(conn.getInputStream()));