使用哪种编码来查找使用默认编码的代码?

4
在Java中从流中读取文本时,常见的错误是忘记指定编码。如果您没有指定任何内容,Java将使用平台默认编码,这最终会导致问题(“但在我的电脑上可以工作!”)。
为了找到这些问题,我想使用一个不常见的默认编码,它应该尽可能地破坏许多I/O操作。这个想法是至少任何ASCII之外的字符都会被弄乱。
我们大多数文档都使用UTF-8编码。ISO-8859-1可能有效,因为它只保留输入(它是字节和字符之间的1:1映射)。任何umlauts都将被读取为两个/三个字节序列。但我想知道是否有更好的选择。
您建议从支持的编码列表中使用哪种编码?

如果你的JVM有一些,EBCDIC是很有趣的。http://en.wikipedia.org/wiki/Extended_Binary_Coded_Decimal_Interchange_Code - Mat
我有EBCDIC(Java中的Cp037),但是当我使用这种编码时,我无法再运行Maven了,因为它尝试使用EBCDIC编码的字符串创建进程...;-) - Aaron Digulla
3个回答

2
默认的UTF-16编码很可能会“破坏”任何不是UTF-16的文档。
但我认为你的方法有误。检测依赖默认编码的不良代码的更好方法是为类似PMD的工具编写一些自定义规则。只需查找使用有问题的String、IO类等构造方法和方法的代码即可。
(采用“使用奇怪的默认编码”的方法存在问题,即你的测试可能无法覆盖所有有问题的代码,或者虽然执行了代码但未能检测到破坏。)

1
UTF-16 与 EBCDIC(Cp037)一样存在问题:ProcessBuilder 突然无法启动进程 :-( 看起来它使用了默认字符集 :-/ 但 PMD 方法值得肯定。 - Aaron Digulla

1

我认为任何16位或32位的UTF都会产生很多“null”字符,这应该会破坏很多字符串。此外,使用带有BOM(字节顺序标记)的编码应该会进一步“破坏”文件。

但我猜测有代码分析工具可以检查是否创建了没有编码的字符串、读取器和写入器。

编辑: FindBugs似乎能够做到这一点:Dm: Reliance on default encoding (DM_DEFAULT_ENCODING)


你如何解决这个问题? - gomathi subramanian
@gomathisubramanian 你的意思是什么?最好的方法可能是使用FindBig或其他代码分析工具来警告您可能存在的问题,并通过指定所需的编码来修复它们。 - Roger Lindsjö
哦,好的好的。明白了。谢谢 Roger。 - gomathi subramanian

1

java.nio.charset.Charset 有一个方法 newDecoder(),它返回一个 Decoder 对象。Deconder 对象有一些方法,如 isAutoDetecting()isChasetDetected()detectedCharset(),这些方法对您的任务似乎非常有用。不幸的是,所有这些方法都是可选的。

我认为您应该获取所有可用字符集 (Charset.availableCharsets()),并首先检查它们是否可以自动检测。因此,当您获取新的流时,应首先尝试使用实现这些可选操作的字符集的内置自动检测机制。

如果没有任何解码器能够检测到字符集,您应该尝试解码流 (就像您所解释的那样),并尝试应用其他字符集来优化此过程,请使用以下标准对字符集进行排序。

首先考虑国家语言的字符集。例如,在处理拉丁字母之前,请尝试使用西里尔字母字符集。

在国家语言的字符集中,请选择具有更多字符的字符集。例如,日文和中文将排在队列的前面。

这种策略的原因是你想尽快失败。如果你的文本不包含日语字符,你必须检查流中的第一个字符以了解它是否不是日语。但是,如果你尝试使用ASCII字符集来解码法语文本,你可能需要读很多字符才能看到第一个è

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