强制执行用户输入的编码标准化&文件阅读器输入

时间:2015-05-19 05:30:43

标签: java unicode encoding ascii

我正在设计一个用于确定给定文本的人类语言的系统。它通过为每种感兴趣的语言存储字典并随后评估用户输入是否对应于字典存储的任何单词来工作。词典击中次数最多的语言是赢家。

我想,为了这两个条目,用户的单词和来自“单词列表”文件的单词匹配编码必须相同,这就是我想要解决的问题。

我从this site获取了单词列表。

当我在我的代码中使用“ ASCII ”中的一切时,一切正常,但当我使用“ Unicode ”中的那些时,没有任何作用。

这让我感到不安,因为我不希望程序得到一些以错误方式编码的输入(以与我的单词列表数据结构冲突的方式)然后失败。

出于这个原因,我想用特定的编码标准化所有输入。我认为“ Unicode ”会更好,因为这是一个用于确定文本的自然语言的系统,我可能会得到一些希腊语,俄语或中文字符,并且从我的理解“ ASCII “高度非标准化。

我目前正在使用Eclipse的控制台来编写输入。

这是我在文件中阅读的方式:

//BufferedReader br = new BufferedReader( new InputStreamReader(new FileInputStream( dir.toString() ), "UTF-8") );

BufferedReader br = new BufferedReader( new FileReader( dir.toString() ) );
String line = null;

BloomFilter<String> bloomFilter;
if (word_holding_directory_path.toLowerCase().contains("/de/")) 
{
    bloomFilter = de_bloomFilter;
} 

这是我阅读用户输入的方式:

//Scanner in = new Scanner( System.in , "UTF-8");
Scanner in = new Scanner(System.in);

System.out.println("Please enter a sentence: ");

String[] input_text = in.nextLine().split("\\s");

正如你所看到的,我试图强制编码为UTF-8(这与Unicode相同,不是吗?),但由于它无法正常工作,我对它进行了评论。

这是我比较单词的方式:

for (String word : input_text) 
{
    String normalized = word.trim().toLowerCase();
    if (words.contains(normalized)) 
    {
        ++count;
    }
}

完整的程序是here on github它非常简短并且相当明确地评论过。

1 个答案:

答案 0 :(得分:1)

您链接的词典似乎是UTF-16LE,而不是UTF-8。您应该相应地在InputStreamReader实例化中修复编码参数。

Unicode和UTF-8最重要的是相同的东西;事实上,说文字是“Unicode”而没有提到编码是不够精确的。 1

(您应该可以猜测,几年前的ZIP文件可能会使用UTF-16LE,这在Windows上仍然是许多用途的默认设置。新资源通常是UTF-8,即使在Windows上也是如此。)

从UTF-16文件中读取一个字符串,并使用正确的控制台编码从控制台中读取包含相同文本的另一个字符串,将生成两个相等的Java字符串。另一方面,如果其中一个输入流上的编码不正确,那么你在字符串中最终得到的结果将是随机的伪造。 (在“火车残骸”场景中,您在两个输入上都有不同的编码错误,并且巧合地获得两个相等的字符串,而实际上两个字符串应该包含不同的文本。)

(不确定UTF-8通常是否适用于控制台,或者特别是在您的环境中 - 我不是Java程序员。)

1 简而言之,抽象的Unicode字符串

U+0066 U+00F6 U+0072

(代表瑞典语单词för)将表示为

0x66 0xC3 0xB7 0x72

在UTF-8中(注意普通ASCII字符如何映射到身份表示)和

0x66 0x00 0xF6 0x00 0x72 0x00

在UTF-16LE中(其中每对字节是一个16位序列,MSB设置为零,而LSB容纳表示的整个重要部分)。

在纯ASCII中,无法表示此字符串;回到过去的时候,它会写成

0x66 0x7C 0x72

其中0x7C恰当是管道字符|,它在硬件中本地映射到字形ö。 (相应地,如果您使用的英语资源应该包含适当的管道字符,那么它也会被渲染为ö;因此Unix管道行grep cat food | xxd将显示为grep cat food ö xxd }。)

稍晚些时候,ISO-8859-1变得流行,这个字符串将表示为

0x66 0xFC 0x72

这当然简单而有效。为什么Unicode也不代表它呢?因为8位编码中只有256个字符,而Unicode要大得多。您根本无法代表上海市машина

相关问题