将汉字数据库kradfile读入R:编码问题

Reading the kanji database kradfile into R: encoding problem

我正在尝试像这样将 kradfile 加载到 R 中:

krad<-readLines("kradfile2",encoding = "UTF-8")
krad<-readLines("kradfile2",encoding = "EUC-JP")

但似乎都无法正确阅读内容。我不知道如何处理编码才能正确读取它。 该文件包含以下说明:

[20] "# Two fonts were used in decomposition so as to include as many glyphs as"     
[21] "# possible.  One apparently based on the JIS X 0212 standard itself, and"      
[22] "# one based on Unicode.  Each JIS X 0212 kanji is represented by 3 bytes"      
[23] "# in EUC-JP encoding, as opposed to the two bytes used in the JIS X 0208"      
[24] "# range, so adjust your software accordingly if necessary."                  

编码后的文本如下所示:

 : °ì Ò± °¢ : °ì ¡Ã °£ : °ì ¡Ã °¤ : °ì ¡Ã ¥Î °¥ : °ì Ц ¥Î Ò± °¦ : ÒÓ ²¦ °§ : °ì ¡Ã ¥Î ¸ý °¨ : °ì ¿Í ÑÄ °© : ¡Ã °ª : ¡Ã Ц ¥Î Öõ °« : ¡Ã Æó °¬ : ¡Ã ×Ä °­ : °ì ¡Ã Æó °® : °ì Ц ¥Î Öõ ½½ ´³ °¯ : Ц °° : °ì Ц °± : Ц ¥Î °² : °ì ¥Î ²µ °³ : ¡Ã Ц ¥Î °´ : ²µ °µ : ²µ Ò¸ °¶ : ²µ Öö °· : ²µ ÒÓ ¸ý °¸ : ²µ ËÎ ¸ý °¹ : °ì ¥Î ²µ Э ¶Ô °º : ²µ ½½ Ω ¿É °» : ²µ ½½ Æü °¼ :

感谢帮助。

该文件看起来有点奇怪,它混合了日语字符的 JIS X 0208-1997 编码和描述性文本的纯 one-byte ASCII 和 spaces,所以它看起来像尽管您必须将每个日文字符的字节对与文件的其余部分分开检测和解码。

例如,文件的第 200 行如下所示:

"\xb1\xa4 : \xb2\xbb \xb3\xad \xcc\xdc \xa5\xcf \xb8\xfd \xc6\xfc Ω"

我不知道 JIS X 0208 编码,但我很确定这在其中是不合法的:它是所有字符的每个字符 2 字节编码,而不仅仅是日文部分。所以你需要以字节的形式读取文件并自己解析它们。

幸运的是,其他人已经做到了。您可以在此处获取该文件的 UTF-8 版本:https://github.com/irrwahn/jiten-pai/blob/master/kradfile.utf8 . There's another version of that here: https://github.com/jmettraux/kensaku/blob/master/data/kradfile-u .

编辑添加:

在评论中您要求提供执行此转换的代码。正如我在那里所说:这样做的方法是将文件作为字节序列读取,并查看每个字节以将其表征为分隔符(space、冒号、换行符)或 JIS X 0208-1997 字符.然后将这些 JIS X 0208-1997 字符转换为您可以使用的编码。第一部分相对容易;我不知道如何进行翻译,因为该编码不在 iconvlist() 中。

这是执行第一部分的代码:

bytes <- readBin("~/temp/kradfile", "int", size=1, signed=FALSE, n=1e6)

# The lines are separated by newline 0x0a values, and the main records
# have 2 byte characters followed by " : ", i.e. 0x20, 0x3a, 0x20.

newline <- 0x0a
space <- 0x20
colon <- 0x3a

newlines <- which(bytes == newline)

# Look through all the lines until we find the main records

for (start in newlines) {
  if (all(bytes[start + 3:5] == c(space, colon, space)))
    break
} 

# Only keep the newlines that start the main records

newlines <- newlines[newlines >= start]

# Now extract the data

result <- vector("list", length = length(newlines))

for (i in seq_along(newlines)) {
  if (i < length(newlines)) {
    kanji <- bytes[newlines[i] + 1:2]
    eol <- newlines[i+1]
    elements <- bytes[(newlines[i] + 6):(eol - 1)]
    # drop the spaces
    elements <- elements[elements != space]
    result[[i]] <- list(kanji = kanji, elements = elements)
  }
}

最后是一长串这样开头的:

head(result, 2)
#> [[1]]
#> [[1]]$kanji
#> [1] 176 161
#> 
#> [[1]]$elements
#> [1] 161 195 176 236 184 253
#> 
#> 
#> [[2]]
#> [[2]]$kanji
#> [1] 176 162
#> 
#> [[2]]$elements
#> [1] 161 195 176 236 184 253

所以第一个汉字有字节 176 161,包含三个元素:161 195、176 236、184 253。将这些转换成可读字符需要 table JIS X 0208-1997 编码,我没有那个。

第二次编辑:

经过一番搜索,我找到了以下内容。我们需要从 kradfile 中的字符中减去 0x80 以获得实际的 JIS X 0208 编码。 iconv() 不支持该编码的 1997 版本,但支持 1990 版本,称之为 "JIS_X0208-1990"。一个棘手的问题是,要处理多字节字符,每个字符的字节都需要作为原始向量出现在列表的条目中。所以这是从原始文件中提取字符的最后一段代码:

for (i in seq_along(result)) {
  code <- as.raw(result[[i]]$kanji - 0x80)
  result[[i]]$kanji <- iconv(list(code), from = "JIS_X0208-1990", to="UTF-8")
  code <- as.raw(result[[i]]$elements - 0x80)
  result[[i]]$elements <- iconv(list(code), from = "JIS_X0208-1990", to="UTF-8")
}
head(result, 2)
#> [[1]]
#> [[1]]$kanji
#> [1] "亜"
#> 
#> [[1]]$elements
#> [1] "|一口"
#> 
#> 
#> [[2]]
#> [[2]]$kanji
#> [1] "唖"
#> 
#> [[2]]$elements
#> [1] "|一口"