R write.csv с кодировкой UTF-16
У меня возникают проблемы с выдачей data.frame с использованием write.csv
с использованием кодировки символов UTF-16.
Справочная информация. Я пытаюсь выписать файл CSV из файла data.frame для использования в Excel. Excel Mac 2011, похоже, не нравится UTF-8 (если я укажу UTF-8 во время импорта текста, символы, отличные от ASCII, отображаются как подчеркивания). Мне повезло, что Excel будет довольствоваться кодировкой UTF-16LE.
Вот пример data.frame:
> foo
a b
1 á 羽
> Encoding(levels(foo$a))
[1] "UTF-8"
> Encoding(levels(foo$b))
[1] "UTF-8"
Итак, я попытался вывести data.frame, выполнив:
f <- file("foo.csv", encoding="UTF-16LE")
write.csv(foo, f)
Это дает мне ASCII файл, который выглядит так:
"","
Если я использую encoding="UTF-16"
, я получаю файл, который содержит только знак байта 0xFE 0xFF
.
Если я использую encoding="UTF-16BE"
, я получаю пустой файл.
Это 64-разрядная версия R 2.12.2 на Mac OS X 10.6.6. Что я делаю неправильно?
Ответы
Ответ 1
Вы можете просто сохранить csv в UTF-8 и позже преобразовать его в UTF-16LE с iconv в терминале.
Если вы настаиваете на выполнении этого в R, может работать следующее: хотя кажется, что iconv
в R имеет некоторые проблемы, см. http://tolstoy.newcastle.edu.au/R/e10/devel/10/06/0648.html
> x <- c("foo", "bar")
> iconv(x,"UTF-8","UTF-16LE")
Error in iconv(x, "UTF-8", "UTF-16LE") :
embedded nul in string: 'f\0o\0o\0'
Как вы можете видеть, что вышеупомянутый связанный патч действительно необходим - который я не тестировал, но если вы хотите сохранить его просто (и противно): просто вызовите программу стороннего iconv внутри R с вызовом system
после сохранение таблицы в csv.
Ответ 2
что-то подобное (write.csv()
просто игнорирует кодировку, поэтому вам нужно выбрать writLines()
или writeBin()
)...
#' function to convert character vectors to UTF-8 encoding
#'
#' @param x the vector to be converted
#' @export
toUTF8 <-
function(x){
worker <- function(x){
iconv(x, from = Encoding(x), to = "UTF-8")
}
unlist(lapply(x, worker))
}
#' function to write csv files with UTF-8 characters (even under Windwos)
#' @param df data frame to be written to file
#' @param file file name / path where to put the data
#' @export
write_utf8_csv <-
function(df, file){
firstline <- paste( '"', names(df), '"', sep = "", collapse = " , ")
char_columns <- seq_along(df[1,])[sapply(df, class)=="character"]
for( i in char_columns){
df[,i] <- toUTF8(df[,i])
}
data <- apply(df, 1, function(x){paste('"', x,'"', sep = "",collapse = " , ")})
writeLines( c(firstline, data), file , useBytes = T)
}
#' function to read csv file with UTF-8 characters (even under Windwos) that
#' were created by write_U
#' @param df data frame to be written to file
#' @param file file name / path where to put the data
#' @export
read_utf8_csv <- function(file){
# reading data from file
content <- readLines(file, encoding = "UTF-8")
# extracting data
content <- stringr::str_split(content, " , ")
content <- lapply(content, stringr::str_replace_all, '"', "")
content_names <- content[[1]][content[[1]]!=""]
content <- content[seq_along(content)[-1]]
# putting it into data.frame
df <- data.frame(dummy=seq_along(content), stringsAsFactors = F)
for(name in content_names){
tmp <- sapply(content, `[[`, dim(df)[2])
Encoding(tmp) <- "UTF-8"
df[,name] <- tmp
}
df <- df[,-1]
# return
return(df)
}