我目前正在使用XSLT开发CSV导出。在我的情况下,CSV文件将使用%99%的Excel,因此我必须考虑Excel行为。
我的第一个问题是csv中的德语特殊字符。即使CSV编码是UTF8,Excel也无法使用UTF8正确打开CSV文件。特殊字符变得怪异的符号。我找到了解决这个问题的方法。我刚刚添加了3个额外的字节( EF BB BF - a.k.a BOM Header )内容字节的开头。因为UTF8 BOM是说'嘿伙计,它是UTF8,正确打开它'到Excel。问题解决了!
我的第二个问题是分离器。默认分隔符可以是逗号或分号,具体取决于区域。我认为它是德国的分号和英国的逗号。所以,为了防止出现这个问题,我不得不在下面添加一行:
<xsl:text>sep=;</xsl:text>
或
<xsl:text>sep=,</xsl:text>
(此分隔符未实现为硬编码)
但是我找不到任何解决方案的问题是,如果添加“sep =;”或者,当使用UT8-BOM生成CSV文件时,文件的开头“sep =”,BOM无法再正确显示特殊字符!我确信BOM字节总是在字节数组的开头。此屏幕截图来自Mac OS X中的MS Excel:
前3个符号属于BOM表头。
你有没有想过这个问题,或者你有什么建议吗?谢谢。
修改
我分享了printcreens。
一个。使用BOM和 <xsl:text>sep=;</xsl:text>
湾只需BOM
Java代码:
// Write the bytes
ServletOutputStream out = resp.getOutputStream();
if(contentType.toString().equals("CSV")) {
// The additional bytes in below is prefix indicates that the content is in UTF-8.
out.write(239);
out.write(187);
out.write(191);
}
out.write(bytes); // Content bytes, in this case XSL
XSL代码:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:text>sep=;</xsl:text>
<table>
...
</table>
</xsl:template>
答案 0 :(得分:8)
您是对的,当有人双击CSV文件时,Excel 2007中无法让它在不同的语言环境中正确加载编码和分隔符。
似乎当您在BOM之后指定sep =时它会忘记BOM告诉它它是UTF-8。
您必须指定BOM,因为在某些区域设置中Excel不会检测到分隔符。例如,在丹麦语中,默认的分隔符是;。如果您输出制表符或逗号分隔文本,则它不会检测到分隔符,而在其他语言环境中,如果您使用分号分隔它不会加载。你可以通过改变windows设置中的locae格式来测试它 - excel然后选择它。
从这个问题: Is it possible to force Excel recognize UTF-8 CSV files automatically?
并且答案似乎唯一的方法是使用带有BOM的UTF16文件编码。
另请注意,根据http://wiki.scn.sap.com/wiki/display/ABAP/CSV+tests+of+encoding+and+column+separator?original_fqdn=wiki.sdn.sap.com 似乎如果你使用带标签分隔符的utf16-le那么它可以工作。
我想知道excel是否读取sep =;然后重新调用方法来获取CSV文本并丢失BOM - 我尝试过给出错误的文本,但我找不到任何可以告诉excel同时接受sep和编码的工作。< / p>
答案 1 :(得分:8)
这是我使用Excel 2013进行测试的结果。
如果你坚持使用UTF-8,有一种解决方法,包括BOM +数据+ sep =;
输入(使用UTF8编码编写)
\ufeffSome;Header;Columns
Wîth;Fàncÿ;Stûff
sep=;
<强>输出
|Some|Header|Columns|
|Wîth|Fàncÿ |Stûff |
|sep=| | |
解决方案的问题是,当Excel正确解释sep=;
时,它会在最后一行的第一列显示sep=
(是的,它会吞下;
)。
但是,如果您可以将文件写为UTF16-LE,那么就有一个实际的解决方案。使用\t
分隔符而不指定sep
,Excel将播放球。
输入(使用UTF16-LE编码编写)
\ufeffSome;Header;Columns
Wîth;Fàncÿ;Stûff
<强>输出
|Some|Header|Columns|
|Wîth|Fàncÿ |Stûff |
答案 2 :(得分:0)
我还不能写评论,但我想谈谈@ Pier-Luc Gendreau的解决方案。虽然可以在欧洲Excel中打开它(默认情况下使用;
作为分隔符)并且具有完全的utf-16LE支持,但是当您指定sep=,
时,显然不可能使用此技术。
解决方案的问题是,虽然Excel解释sep =;正确地,它在最后一行的第一列显示sep =(是的,它吞下了;)。
对我来说,如果我指定的分隔符不是默认分隔符(在我的情况下是;
),它就不起作用所以我假设Excel没有正确解释最后一行并吞下最后一个分隔符,因为这是默认行为。
如果我错了,请纠正我