2011-03-10 115 views
10

我在使用UTF-16字符编码使用write.csv输出数据帧时遇到问题。R使用UTF-16编码的write.csv

背景:我试图从data.frame中写出一个CSV文件以便在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",我得到一个空文件。

这是在Mac OS X 10.6.6上的R 2.12.2的64位版本。我究竟做错了什么?

+2

为了记录在案,跆拳道是错Excel和UTF-8?我的意思是,来吧,这是2011. – 2011-03-11 01:43:52

回答

6

你可以简单地保存CSV在UTF-8,后来在终端它iconv转换为UTF-16LE。

如果你坚持R中这样做,下面可能工作 - althought似乎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' 

正如你可以看到上面的链接补丁是真的需要 - 我没有测试过,但如果你想保持它的模拟(和讨厌):只需在保存表格csv后拨打system调用R内的第三方iconv程序。

+0

我输出UTF-8后一直使用iconv,但我希望我只是在做一些错误的事,而R会很乐意直接输出UTF-16。我猜这可能不是这样的...... – 2011-03-11 01:41:43

+1

@Daniel Dickison:看起来如此:(如果可以的话,我建议你在保存数据框后调用iconv,只需使用'system'函数 - 这样你不必开始一个单独的程序,你也可以通过编写一个保存* csv *的小函数来自动执行这个过程,并且也可以转换为所需的编码,无论如何,祝你好运! – daroczig 2011-03-11 20:43:09

+1

为什么UTF-16 iconv问题仍然没有在R中修复(修补程序的日期为2010年)?在R中,我仍然看不到在“2016年”中读取或编写UTF-16(Windows)编码文本文件的简单“本机”方式:-( – 2016-02-04 22:03:33

4

类似的东西可能会做(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) 
}