九月= “;”声明破坏了由XSL生成的CSV文件中的utf8 BOM

时间:2013-12-05 09:07:14

标签: excel xslt csv

我目前正在使用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:

enter image description here

前3个符号属于BOM表头。

你有没有想过这个问题,或者你有什么建议吗?谢谢。

修改

我分享了printcreens。

一个。使用BOM和 <xsl:text>sep=;</xsl:text>

enter image description here

湾只需BOM

enter image description here

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>

3 个答案:

答案 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没有正确解释最后一行并吞下最后一个分隔符,因为这是默认行为。

如果我错了,请纠正我