我以编程方式将数据(使用PHP 5.2)导出到.csv测试文件中.
示例数据:( Numéro 1注意重音e).数据是utf-8(没有前置BOM).
当我在MS Excel中打开此文件时显示为Numéro 1.
我可以在文本编辑器(UltraEdit)中打开它,正确显示它.UE报告角色是decimal 233.
如何在.csv文件中导出文本数据以便MS Excel正确呈现它,最好不强制使用导入向导或非默认向导设置?
我正在使用此代码通过OpenCSV将波斯语单词添加到csv文件中:
String[] entries="\u0645 \u062E\u062F\u0627".split("#");
try{
CSVWriter writer=new CSVWriter(new OutputStreamWriter(new FileOutputStream("C:\\test.csv"), "UTF-8"));
writer.writeNext(entries);
writer.close();
}
catch(IOException ioe){
ioe.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
当我打开生成的csv文件时,在Excel中,它包含"ứỶờịỆ".其他程序,如notepad.exe没有此问题,但我的所有用户都使用MS Excel.
用SuperCSV替换OpenCSV并不能解决这个问题.
当我手动将波斯字符键入csv文件时,我没有任何问题.
所以我们有这个支持UTF8数据的网络应用程序.万岁UTF8.我们可以将用户提供的数据导出为CSV没问题 - 此时它仍然是UTF8.问题是当你在Excel中打开一个典型的UTF8 CSV时,它会将其读作ANSII编码文本,并因此尝试读取两个字节的字符,如ø和ü作为两个单独的字符,最终会失败.
所以我已经做了一些挖掘(Intervals人员在这里有一个有趣的帖子),并且有一些有限的,如果有可笑的烦人选择.其中:
看起来无论如何,我可能会继续为那些不使用它的人提供一个普通的CSV文件,以及一个单独的Excel下载选项.
生成那个能正确支持UTF8的Just-For-Excel文件的最简单方法是什么,亲爱的Stack Overflowers?如果最简单的选项仅支持最新版本的Excel,那仍然是有意义的.
我在Rails堆栈上执行此操作,但很奇怪.Net-ers和任何框架上的人员如何处理这个问题.我自己在几个不同的环境中工作,这绝对是一个将再次出现的问题.
更新2010-10-22:我们在时间跟踪系统Tempo中使用Ruport gem在我第一次发布此问题时提供CSV导出.我的一个同事Erik Hollensbee为Ruport提供了一个快速过滤器,为我们提供了实际的Excel XSL输出,我想我会在这里分享其他任何红宝石:
require 'rubygems'
require 'ruport'
require 'spreadsheet'
require 'stringio'
Spreadsheet.client_encoding = "UTF-8"
include Ruport::Data
class Ruport::Formatter::Excel < Ruport::Formatter
renders :excel, :for => Ruport::Controller::Table
def output
retval = StringIO.new
if options.workbook
book = options.workbook
else
book = Spreadsheet::Workbook.new
end
if options.worksheet_name
book_args = { :name => options.worksheet_name }
else
book_args = { }
end
sheet = …Run Code Online (Sandbox Code Playgroud) 的字节顺序标记(BOM)为UTF-8是EF BB BF,如在说明中的Unicode 9的部分23.8规范(搜索“签名”)。
Java中的许多解决方案都只是一个简单的一行代码:
replace("\uFEFF", "")
Run Code Online (Sandbox Code Playgroud)
我不明白这为什么有效。
这是我的测试代码。我在调用后检查二进制文件String#replace,我发现 EF BB BF 已被删除。查看此代码在 IdeOne.com 上实时运行。
太神奇了。为什么这样做?
@Test
public void shit() throws Exception{
byte[] b = new byte[]{-17,-69,-65, 97,97,97};//EF BB BF 61 61 61
char[] c = new char[10];
new InputStreamReader(new ByteArrayInputStream(b),"UTF-8").read(c);
byte[] bytes = new StringBuilder().append(c).toString().replace("\uFEFF", "").getBytes();//
for(byte bt: bytes){//61 61 61, we can see EF BB BF is indeed removed
System.out.println(bt);
}
}
Run Code Online (Sandbox Code Playgroud)