有没有简便的方法可以避免处理文本编码问题?
如果你从一个字符串开始,你也可以这样做:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
在处理文本编码问题时,您无法真正避免,但是Apache Commons中存在现有的解决方案:
Reader
转 InputStream
: ReaderInputStream
Writer
转 OutputStream
: WriterOutputStream
您只需要选择所需的编码即可。
在Java中,Reader处理字符,InputStream处理字节。编码指定了您希望将字符表示为字节的方式,因此您不能忽略这个问题。至于避免问题,我的建议是:选择一个字符集(例如"UTF-8")并坚持使用它。
关于如何实际操作,正如已经指出的那样,"这些类的显而易见的名称是ReaderInputStream和WriterOutputStream。" 令人惊讶的是,尽管Java库中包括了相反的类InputStreamReader和OutputStreamWriter,但这些类却没有被包含。
因此,许多人都提出了自己的实现,包括Apache Commons IO。根据许可问题,您可能可以在项目中包含commons-io库,甚至复制部分源代码(可在此处下载:这里)。
如您所见,两个类的文档都指出“JRE支持的所有字符集编码都能正确处理”。
N.B. 这里提到了另一个答案中的评论这个漏洞。但是它影响的是Apache Ant ReaderInputStream类(在这里),而不是Apache Commons IO ReaderInputStream类。
请注意,如果您的起点是一个字符串,您可以跳过创建StringReader,使用org.apache.commons.io.IOUtils从Commons IO一次性创建一个InputStream,如下所示:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
当然,你仍然需要考虑文本编码,但至少转换是在一个步骤中完成的。new ByteArrayInputStream(report.toString().getBytes("utf-8"))
,它需要在内存中再分配两份报告的副本。如果报告很大,那就不好了。请看我的回答。 - Oliv使用:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
这种方法不需要将内容先转换为String
,再转换为byte[]
,这样会在报告很大的情况下分配更多的堆内存。它会在读取流时即时地从StringBuffer中转换为字节。它使用了Apache Commons IO项目中的CharSequenceInputStream。您是否正在尝试将Reader
的内容写入OutputStream
?如果是这样,您可以更轻松地将OutputStream
包装在OutputStreamWriter
中,并将Reader
中的char
写入Writer
,而不是试图将reader转换为InputStream
:
final Writer writer = new BufferedWriter(new OutputStreamWriter( urlConnection.getOutputStream(), "UTF-8" ) );
int charsRead;
char[] cbuf = new char[1024];
while ((charsRead = data.read(cbuf)) != -1) {
writer.write(cbuf, 0, charsRead);
}
writer.flush();
// don't forget to close the writer in a finally {} block
ReaderInputStream
实现应该需要更少的内存--无需一次性将所有字节存储在数组中。 - Piotr Findeisen