Skip to main content

代替文字を含むShift-JISのテキストファイルをRで読み込む(おまけにPythonも)

概要

Question

以下のdata.txtというファイル名のShift-JISのテキストファイルを考えます。ただし、代替文字(Replacement Character, UnicodeでU+FFFD)が含まれる行が存在する可能性があります。

りんご
みかん
バナナ
(以下略)

いま、このテキストファイルを、代替文字は削除したうえで1行が1要素の文字列ベクトル(c("りんご", "みかん", "バナナ"...))として読み込みたいです。ただし、環境はWindows, RはR>=4.2.0のバージョンとします。

Answer

回答は一例です。

readr::read_lines_raw("data.txt") %>% 
  stringi::stri_encode(from="Shift-JIS") %>% 
  stringr::str_remove_all("\ufffd")

環境

version  R version 4.2.1 (2022-06-23 ucrt)
os       Windows 10 x64 (build 19045)
system   x86_64, mingw32
ui       RStudio
language (EN)
collate  Japanese_Japan.utf8
ctype    Japanese_Japan.utf8
tz       Asia/Tokyo
date     2022-11-21
rstudio  2022.07.1+554 Spotted Wakerobin (desktop)

(一部割愛)

readr: 2.1.3
stringi: 1.7.8
stringr: 1.4.1

説明

data.txtに代替文字が含まれていなければ、以下で問題ありません。代替文字を含む場合でも、ファイルがUTF-8やEUC-JPの場合はencodingをそれに変えれば上記の環境で同様に問題なく読み込めました。

readr::read_lines("data.txt", locale=readr::locale(encoding="Shift-JIS"))

しかし、代替文字を含むShift-JISのファイルの場合、Error: Invalid Multibyte Sequenceというエラーが出てRStudioがクラッシュします。そのため、一旦raw形式で読み込んでから文字列に直します。raw形式で読み込む関数は、例えばreadr::read_lines_rawがあります。

次に、raw形式から文字列に変換する必要がありますが、rawToCharを用いると文字化けしてしまいます。理由は私にはよく分かっていないのですが、こちらのStack Overflowのアンサーによると(Encoding and raw in R - Stack Overflow)、charToRawの関数ヘルプにはエンコーディングを考慮しないと記載があるので、rawToCharも同様にエンコーディングが考慮されないのではないか、とのことです。R>=4.2.0の環境では日本語環境のWindowsでも文字のロケールがUTF-8ですので、辻褄が合います。

したがって、エンコーディングを考慮してrawから文字列に変換するstringi::stri_encodeを用います。

最後にstringr::str_remove_allで代替文字である\ufffdを削除すれば完成です。

Python版

おまけにPythonで同じことをするコードを載せておきます。バイナリモードで1行ずつ読み込んでShift-JISに変換すればOKです。line_binary.decodeignoreとすればReplacement Characterを読み込んだ上で削除されますが、ここをreplaceとしてからre.subで削除したり他の文字に置き換えることも可能です。

res = []
with open("data.txt", "rb") as f:
    while True:
        line_binary = f.readline()
        line = line_binary.decode("Shift-JIS", "ignore")
        if line == "":
            break
        res.append(line)

参考にさせていただいたサイト