始めにヌルを含む巨大なテキストファイルを作成する。以下は文字コードがUTF-8の環境のため(3×5+2)×2×10^7=340,000,000バイト(約324MB)のテキストファイルを作成している。ファイルの行数は10^7=10,000,000行。それぞれの行は苗字と名前の間にヌル(0x00)が挟まれている。
> Sys.getlocale()
[1] "LC_COLLATE=Japanese_Japan.utf8;LC_CTYPE=Japanese_Japan.utf8;LC_MONETARY=Japanese_Japan.utf8;LC_NUMERIC=C;LC_TIME=Japanese_Japan.utf8"
> ra1 <- unlist(iconv("石見", toRaw = TRUE))
> ra2 <- unlist(iconv("舞菜香", toRaw = TRUE))
> ra3 <- unlist(iconv("和多田", toRaw = TRUE))
> ra4 <- unlist(iconv("美咲", toRaw = TRUE))
> ra <- c(ra1, as.raw(0), ra2, as.raw(0x0a), ra3, as.raw(0), ra4, as.raw(0x0a))
> writeBin(rep(ra, 10 ^ 7), "temp.txt")
> file.info(dir(patter = "temp\\.txt"))["size"]
size
temp.txt 3.4e+08
scan関数を使用して読み込む場合は、skipNulオプションにTRUEを指定しないとうまく読み込むことができない。
> lns <- scan("temp.txt", what = character(), sep = "\n", quiet = TRUE)
警告メッセージ:
scan("temp.txt", what = character(), sep = "\n", quiet = TRUE) で:
入力文字列の中に nul が埋め込まれています
> length(lns)
[1] 20000000
> lns[1:3]
[1] "石見" "和多田" "石見"
> lns <- scan("temp.txt", what = character(), sep = "\n", quiet = TRUE, skipNul = TRUE)
> length(lns)
[1] 20000000
> lns[1:3]
[1] "石見舞菜香" "和多田美咲" "石見舞菜香"
read.table関数を使用して読み込む場合も、skipNulオプションにTRUEを指定しないとうまく読み込むことができない。
> dtf <- read.table("temp.txt", header = FALSE, sep = "\n")
警告メッセージ:
1: read.table("temp.txt", header = FALSE, sep = "\n") で:
line 1 appears to contain embedded nulls
2: read.table("temp.txt", header = FALSE, sep = "\n") で:
line 2 appears to contain embedded nulls
(表示省略)
入力文字列の中に nul が埋め込まれています
> nrow(dtf)
[1] 20000000
> head(dtf, 3)
V1
1 石見
2 和多田
3 石見
> dtf <- read.table("temp.txt", header = FALSE, sep = "\n", skipNul = TRUE)
> nrow(dtf)
[1] 20000000
> head(dtf, 3)
V1
1 石見舞菜香
2 和多田美咲
3 石見舞菜香
それぞれの関数で読み込みに要する時間を計測してみる。
> system.time(
+ scan("temp.txt", what = character(), sep = "\n", quiet = TRUE, skipNul = TRUE)
+ )
ユーザ システム 経過
3.06 0.14 3.86
> system.time(
+ scan("temp.txt", what = character(), sep = "\n", quiet = TRUE, skipNul = TRUE)
+ )
ユーザ システム 経過
3.35 0.14 3.89
> system.time(
+ read.table("temp.txt", header = FALSE, sep = "\n", skipNul = TRUE)
+ )
ユーザ システム 経過
3.06 0.09 4.03
> system.time(
+ read.table("temp.txt", header = FALSE, sep = "\n", skipNul = TRUE)
+ )
ユーザ システム 経過
2.92 0.20 4.06
scan関数の方が若干早い。なお、単純にテキストファイルを読み込むだけであればreadrパッケージのfread関数やread_lines関数のほうが高速に動作するが、以下の例のとおりにヌルを含むとうまく動作をしない。これを制御するオプションは無いようだ。
> library(readr)
> fread("temp.txt", sep = "\n")
fread("temp.txt", sep = "\n") でエラー:
文字列の中に nul が埋め込まれています: '石見\0舞菜香'
追加情報: 警告メッセージ:
fread("temp.txt", sep = "\n") で:
Previous fread() session was not cleaned up properly. Cleaned up ok at the beginning of this fread() call.
> read_lines("temp.txt", progress = FALSE)
character(0)