编写从Java中读取文本的代码时常见的错误是忘记指定编码。如果您没有指定任何内容,Java将使用平台默认编码,最终会导致问题(“但它可以在我的计算机上运行!”)。
为了找到这些问题,我想使用一个不常见的默认编码,它应该尽可能多地打破I / O操作。这个想法是至少在ASCII之外的任何字符都会受到损坏。
我们的大多数文档都使用UTF-8编码。 ISO-8859-1可能有效,因为它只是保留输入(它是字节和字符之间的1:1映射)。任何变音符号都将读取两个/树字节序列。但我想知道我们是否可以做得更好。
您建议在list of supported encodings使用哪种编码?
答案 0 :(得分:2)
UTF-16的默认编码很有可能“破坏”任何非UTF-16的文档。
但我认为你这样做是错误的。检测依赖于默认编码的狡猾代码的更好方法是为PMD之类的内容编写一些自定义规则。只需查看在String
上使用有问题的方法和构造函数的代码,IO类等等。
(“使用奇怪的默认编码”方法的问题是,您的测试可能不足以执行所有违规代码,或者它可能会运行代码但不会检测到错误。)
答案 1 :(得分:1)
我认为16位或32位UTF中的任何一位都会给你很多“空”字符,这些字符应该会破坏很多字符串。使用BOM(字节顺序标记)也应该进一步“破坏”文件。
但我猜有些代码分析工具可以检查是否创建了没有编码的字符串,读者和编写器。
编辑: FindBugs似乎能够做到这一点:Dm: Reliance on default encoding (DM_DEFAULT_ENCODING)
答案 2 :(得分:1)
java.nio.charset.Charset
方法newDecoder()
返回Decoder
。 Deconder的方法isAutoDetecting()
,isChasetDetected()
和detectedCharset()
似乎对您的任务有用。不幸的是所有这些方法都是可选
我认为您应该使用所有可用的字符集(Charset.availableCharsets()
)并首先检查它们是否可自动检测。因此,当您获得新流时,首先尝试使用内置的自动检测机制来实现这些可选操作的字符集。
如果这些解码器中没有一个可以检测到chaset,你应该尝试解码流(如你所解释的)尝试应用其他字符集。要优化流程,请尝试使用以下条件对字符集进行排序。
首先是国家字母表。例如,在处理拉丁字母的那些之前尝试西里尔字符集。
在国家字母表中,选择一个具有更多字符的字母表。例如,日语和中文将在队列的开头。
这种策略的原因是你希望尽可能快地失败。如果您的文字不包含日文字符,则必须检查流中的第一个字符,以了解它是不是日文。但是,如果您尝试使用ASCII字符集来解码法语文本,则在看到第一个è
之前,您可能需要阅读很多字符。