如何确定Java程序是否使用UTF-8编码

7

我最近发现依赖JVM的默认编码会导致错误。在处理 StringInputStreams 等内容时,我应该明确使用特定的编码,比如 UTF-8

我有一个庞大的代码库需要扫描以确保这一点。有没有人能够建议一些比搜索整个代码库更简单的方法来检查这一点。

谢谢 Nayn


我阅读了这篇文章:https://dev59.com/k3I-5IYBdhLWcg3wpaF1 - Nayn
你是否在某处指定了除utf8以外的编码方式? Java中字符串默认为utf8,所以我认为这里没有问题。 - Imre L
2
@Imre:当你读取/写入那些字符作为来自/去往外部源的字符时,问题将会显现出来,这些外部源使用不同的编码(默认情况下),例如磁盘文件系统、数据存储(数据库)、网络连接(HTTP)等。 - BalusC
2
@Imre 不是的,在Java中字符串默认不是UTF-8编码。字符串由16位Unicode字符组成。如果你从文件中读取文本或者向文件中写入文本,那些16位Unicode字符将会被编码为平台相关的默认字符编码。默认编码并不总是UTF-8。 - Jesper
4个回答

4
System.getProperty("file.encoding")

返回用于i/o操作的虚拟机编码方式

您可以通过传递-Dfile.encoding=utf-8来设置它。


1
请查看我在评论中提到的线程。上述属性是特定JVM实现的内部实现细节。在Java 1.5和1.6中,使用此属性的方式有所不同。 - Nayn
这不是。请完整阅读已接受的答案 :) 这是一个标准设置,确定默认字符集。 - Bozho
1
将属性设置为正确的代码就像这样是一种极其不合理的黑客行为。 - Tom Hawtin - tackline
@Tom 我不同意你的看法。虽然最好不要依赖这个(我从不这样做),但使用虚拟机参数是合法的。 - Bozho
我必须承认,如果不将系统属性设置为-Dfile.encoding=utf-8,我无法解决这个问题。我尝试了所有可能的方法来在任何可能的地方设置编码。 - Nayn

3

虽然不是直接答案,但为了方便工作,值得知道的是,在一个相当不错的IDE中,你可以搜索使用了InputStreamReaderOutputStreamWriterString#getBytes()String(byte[])Properties#load()URLEncoder#encode()URLDecoder#decode()等方法的地方,并传递字符集进行更新。你还需要搜索FileReaderFileWriter,并将它们替换为前两个提到的类。的确,这是一项繁琐的任务,但非常值得,并且我更喜欢这种方法而不是依赖于特定环境。

例如,在Eclipse中,选择感兴趣的项目,按下Ctrl+H,切换到Java Search选项卡,输入InputStreamReader,勾选Search For选项中的Constructor,选择只有Sources作为Search In选项,然后执行搜索。


1
FileReader 是坏东西。我不知道这些危险的 API 方法/构造函数的全面列表。 - Tom Hawtin - tackline

0
依赖JVM的默认编码会导致错误。确实,当进行编码/解码时,应始终指定字符集。
如果您对所有编码/解码使用一个默认全局字符集(并不总是足够),则可以使用Bozho的答案:在JVM参数或某些静态初始化器中指定已知的固定默认值。
但最好的做法是搜索代码中的所有隐式字符集规范,并将它们替换为明确的字符集编码。一些典型的方法/类包括:FileWriter、FileReader、InputStreamReader、OutputStreamWriter、String#getBytes() 以及 String(byte[])。

3
需要注意的是,FileWriterFileReader 不能被更改以使用指定的编码方式。应该分别替换为 OutputStreamWriterInputStreamReader - BalusC

0

如果文件是在服务器上使用本地工具进行操作,可能需要将编码设置为System.getProperty("file.encoding")。我曾经遇到过两种方式的错误。

最佳实践是了解使用的字符集,并进行设置。此外,如果该文件用于与另一个应用程序进行接口,则应定义所使用的字符集。这可能是Windows代码页或不同的UTF格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接