Как правильно обрабатывать экранированные символы Unicode в R, например Эм тире (-) - PullRequest
10 голосов
/ 10 февраля 2012

У меня проблемы с обработкой экранированных символов Юникода в R, особенно с теми, которые встречаются при получении информации из MediaWiki API.Я нашел бы строку JSON, такую ​​как

{"query":{"categorymembers":[{"ns":0,"title":"Banach\u2013Tarski paradox"}]}}

, которая должна быть совершенно правильной, но при чтении через fromJSON() я получаю:

snip...
[1] "Banach\023Tarski paradox"

Изначально я думал, что это просто проблема сRJSONIO, но я сталкиваюсь с похожими проблемами с scan() и readLines().Я предполагаю, что мне не хватает чего-то очень простого.

Я не могу на самом деле привести полностью воспроизводимый пример, используя only R, потому что если я отправлю "em \ u2013dash" в файл через запись() (или некоторая эквивалентная функция) R автоматически преобразует их в тире.Так что здесь идет.Создайте текстовый файл с именем test1 со следующим:

"em\u2013dash" "em–dash" " em \u2013 dash"

Затем загрузите R (для любого пути к файлу):

> scan( file = "~/R/test1", what = "character", encoding = "UTF-8")
Read 3 items
[1] "em\\u2013dash"    "em–dash"          " em \\u2013 dash"
> readLines("~/R/test1", warn = FALSE, encoding = "UTF-8")
[1] "\"em\\u2013dash\" \"em–dash\" \" em \\u2013 dash\""

Добавленный escape-символ вызывает мои проблемыс fromJSON().Я мог бы просто удалить их, но, вероятно, сломал бы что-то еще в процессе, и я думаю, что есть более простое решение.Благодарю.

Вот информация о сеансе:

R version 2.14.1 (2011-12-22)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)

locale:
[1] C/en_US.UTF-8/C/C/C/C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] RJSONIO_0.98-0

loaded via a namespace (and not attached):
[1] tools_2.14.1

Ответы [ 3 ]

9 голосов
/ 14 февраля 2012

На самом деле это не ошибка в RJSONIO. Он предназначен для ожидания строки, которая была прочитана R и в которой уже обработаны не-ASCII символы. Когда кто-то передает ему строку с \ u, он не был обработан, но экранирован. На моей машине с языковым стандартом en_US.UTF-8 команда

fromJSON('{"query":{"categorymembers":[{"ns":0,"title":"Banach\u2013Tarski paradox"}]}}')

производит

$query
$query$categorymembers
$query$categorymembers[[1]]
$query$categorymembers[[1]]$ns
[1] 0

$query$categorymembers[[1]]$title
[1] "Banach–Tarski paradox"

Обратите внимание, что перед символом стоит \u, а не \\u. Посмотрите, как это выглядит в R, когда вы просто вводите эту строку.

Таким образом, проблема выше по потоку от fromJSON () - почему строка содержит \ u.
Я могу добавить поддержку в RJSONIO для обработки таких необработанных строк.

5 голосов
/ 10 февраля 2012

Это ошибка в RJSONIO, как вы можете ясно увидеть:

> RJSONIO::fromJSON('{"x":"foo\\u2013bar"}')
           x 
"foo\023bar" 

Она прекрасно работает в rjson:

> rjson::fromJSON('{"x":"foo\\u2013bar"}')
$x
[1] "foo–bar"

и доказать, что этоправильное значение:

 > Sys.setlocale("LC_ALL", "C")
[1] "C/C/C/C/C/en_US.UTF-8"
> rjson::fromJSON('{"x":"foo\\u2013bar"}')
$x
[1] "foo<U+2013>bar"

В вашем анализе вы запутались из-за напечатанной строки по сравнению с фактической строкой.print указывает его содержимое для печати - если вы хотите увидеть фактическую строку, вы можете использовать cat или charToRaw.Также scan не интерпретирует побег, поэтому вы получаете то, что даете.

1 голос
/ 08 июля 2014

Я думаю, что основная проблема заключается в том, что опция libjson JSON_UNICODE не включена в RJSONIO. Однако кажется, что проблема не проявляется, когда ввод UTF-8 закодирован:

library(RJSONIO)
x = "北京填鴨们"
identical(x, fromJSON(toJSON(x)))
# [1] TRUE

Проблема появляется, только когда для ввода используются экранированные символы JSON. В этих случаях RJSONIO, кажется, генерирует latin1 вывод, но не помечает правильно установить кодировку:

x <- fromJSON('["Z\\u00FCrich"]')
print(x)
# [1] "Z\xfcrich"

nchar(x)
#Error in nchar(x) : invalid multibyte string 1

В этом простом примере мы можем исправить это, вручную установив кодировку latin1:

#Set the correct encoding
Encoding(x) <- "latin1"
print(x)
#[1] "Zürich" 

Тем не менее, это, конечно, не будет работать для символов за пределами набора latin1:

#This should be: "填"
fromJSON('["\\u586B"]')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...