为什么这些相同的 Unicode 字符串有不同的序列化形式?
Why do these identical Unicode strings have different serialized forms?
当我将 R 源代码中带有非 ASCII 字符的字符串文字与通过命令行传入的相同字符串进行比较时,这两个字符串测试为 identical
并且具有相同的 charToRaw
表示,但 serialize
不同。这是怎么回事?这两个字符串不是 UTF-8 格式吗?
要重现这个,试试这个 shell 脚本(我是 运行 Dash 0.5.10.2-7 和 Ubuntu 20.10 上的 R 4.0.2):
echo 'x="α"' > program.R
R --vanilla -q -e \
'source("program.R")
print(identical(x, "α"))
print(identical(charToRaw(x), charToRaw("α")))
print(identical(serialize(x, NULL), serialize("α", NULL)))'
产生
> source("program.R")
> print(identical(x, "α"))
[1] TRUE
> print(identical(charToRaw(x), charToRaw("α")))
[1] TRUE
> print(identical(serialize(x, NULL), serialize("α", NULL)))
[1] FALSE
这可能会显示正在发生的事情
echo 'x="α"' > program.R
R --vanilla -q -e \
'source("program.R")
y="α"
.Internal(inspect(x))
.Internal(inspect(y))'
对我来说
> .Internal(inspect(x))
@558f4edc1630 16 STRSXP g0c1 [REF(3)] (len=1, tl=0)
@558f4edc15f8 09 CHARSXP g0c1 [REF(1),gp=0x20] [cached] "α"
> .Internal(inspect(y))
@558f4edd3860 16 STRSXP g0c1 [REF(2)] (len=1, tl=0)
@558f4edd3898 09 CHARSXP g0c1 [REF(3),gp=0x28,ATT] [UTF8] [cached] "α"
所以x
和y
的值是不一样的。我不是所有这些值的专家,但 gp=
值显示了字符串属性。这些差异是导致序列化差异的原因。据我所知,您在获取文件时设置的字符串具有未确定的编码。它不假定为 UTF-8。如果当您 source()
文件时明确指定编码,那么序列化将是相同的。
所以当我运行
echo 'x="α"' > program.R
R --vanilla -q -e \
'source("program.R", encoding="UTF-8")
print(identical(x, "α"))
print(identical(charToRaw(x), charToRaw("α")))
print(identical(serialize(x, NULL), serialize("α", NULL)))'
我明白了
> print(identical(x, "α"))
[1] TRUE
> print(identical(charToRaw(x), charToRaw("α")))
[1] TRUE
> print(identical(serialize(x, NULL), serialize("α", NULL)))
[1] TRUE
因此,将source("program.R")
替换为source("program.R", encoding="UTF-8")
使得最后的支票出来TRUE
。同样,您可以添加 x <- enc2utf8(x)
或 Encoding(x) <- "UTF-8"
.
当我将 R 源代码中带有非 ASCII 字符的字符串文字与通过命令行传入的相同字符串进行比较时,这两个字符串测试为 identical
并且具有相同的 charToRaw
表示,但 serialize
不同。这是怎么回事?这两个字符串不是 UTF-8 格式吗?
要重现这个,试试这个 shell 脚本(我是 运行 Dash 0.5.10.2-7 和 Ubuntu 20.10 上的 R 4.0.2):
echo 'x="α"' > program.R
R --vanilla -q -e \
'source("program.R")
print(identical(x, "α"))
print(identical(charToRaw(x), charToRaw("α")))
print(identical(serialize(x, NULL), serialize("α", NULL)))'
产生
> source("program.R")
> print(identical(x, "α"))
[1] TRUE
> print(identical(charToRaw(x), charToRaw("α")))
[1] TRUE
> print(identical(serialize(x, NULL), serialize("α", NULL)))
[1] FALSE
这可能会显示正在发生的事情
echo 'x="α"' > program.R
R --vanilla -q -e \
'source("program.R")
y="α"
.Internal(inspect(x))
.Internal(inspect(y))'
对我来说
> .Internal(inspect(x))
@558f4edc1630 16 STRSXP g0c1 [REF(3)] (len=1, tl=0)
@558f4edc15f8 09 CHARSXP g0c1 [REF(1),gp=0x20] [cached] "α"
> .Internal(inspect(y))
@558f4edd3860 16 STRSXP g0c1 [REF(2)] (len=1, tl=0)
@558f4edd3898 09 CHARSXP g0c1 [REF(3),gp=0x28,ATT] [UTF8] [cached] "α"
所以x
和y
的值是不一样的。我不是所有这些值的专家,但 gp=
值显示了字符串属性。这些差异是导致序列化差异的原因。据我所知,您在获取文件时设置的字符串具有未确定的编码。它不假定为 UTF-8。如果当您 source()
文件时明确指定编码,那么序列化将是相同的。
所以当我运行
echo 'x="α"' > program.R
R --vanilla -q -e \
'source("program.R", encoding="UTF-8")
print(identical(x, "α"))
print(identical(charToRaw(x), charToRaw("α")))
print(identical(serialize(x, NULL), serialize("α", NULL)))'
我明白了
> print(identical(x, "α"))
[1] TRUE
> print(identical(charToRaw(x), charToRaw("α")))
[1] TRUE
> print(identical(serialize(x, NULL), serialize("α", NULL)))
[1] TRUE
因此,将source("program.R")
替换为source("program.R", encoding="UTF-8")
使得最后的支票出来TRUE
。同样,您可以添加 x <- enc2utf8(x)
或 Encoding(x) <- "UTF-8"
.