csv中的字符编码

时间:2014-12-29 13:57:43

标签: java unix csv encoding utf-16le

我们需要从Oracle DB表中选择数据并将该数据转储到csv文件和普通管道分隔文本文件中。在应用程序上提供用户链接,以便用户可以查看生成的csv /文本文件。

由于涉及到很多解析,所以我们编写了一个Unix shell脚本,并从Struts / J2ee应用程序中调用它。

之前我们在生成的文件中丢失了中文和罗马字符,生成的文件中有us-ascii字符集(cheked using-> file -i)。后来我们使用NLS_LANG=AMERICAN_AMERICA.AL32UTF8,这给了我们utf-8格式的文件。

但是这些角色仍然是胡言乱语,所以我们再次尝试使用iconv命令并将utf-8文件转换为utf-16le charset。 iconv -f utf-8 -t utf-16le $recordFile > $tempFile

这适用于生成的文本文件。但是使用CSV,中文和罗马字符仍然不正确。现在,如果我们在记事本中打开此csv文件并通过按键盘上的Enter键给出换行符,请将其保存。使用MS-Excel打开它,所有字符都很好,包括中文和罗马文,但现在每行的文本都是单行而不是列。

不确定发生了什么。

Java代码

PrintWriter out = servletResponse.getWriter(); 
servletResponse.setContentType("application/vnd.ms-excel; charset=UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setHeader("Content-Disposition","attachment; filename="+ fileName.toString());                   
FileInputStream fileInputStream = new FileInputStream(fileLoc + fileName);  
int i;   
while ((i=fileInputStream.read()) != -1) {  
 out.write(i);   
} 
fileInputStream.close();   
out.close();    

如果我错过了任何细节,请告诉我。 感谢所有人抽出时间来完成这项工作。

2 个答案:

答案 0 :(得分:2)

能够解决它。首先,Aaron提到删除了UTF-16LE编码以避免将来出现问题并将编码文件转移到UTF-8。将Java代码中的PrintWriter更改为OutputStream,并且能够在文本文件中看到正确的字符。

CSV仍然显示垃圾。我们知道我们需要在文件开头添加EF BB BF,因为像BOM这样的MS-Excel感知软件需要它。因此,如下所示更改Java代码是csv的技巧。

OutputStream out = servletResponse.getOutputStream();
os.write(239); //0xEF
os.write(187); //0xBB
out.write(191); //0xBF               
FileInputStream fileInputStream = new FileInputStream(fileLoc + fileName);  
int i;   
while ((i=fileInputStream.read()) != -1) {  
    out.write(i);   
} 
fileInputStream.close();  
out.flush();
out.close();

答案 1 :(得分:1)

与Unicode问题一样,转换链的每一步都必须完美运行。如果你在一个地方犯了错误,数据将被无声地破坏。没有简单的方法可以找出它发生的位置,你必须调试代码或编写单元测试。

上面的Java代码仅在文件实际包含UTF-8编码数据时才有效;它没有神奇地"找出文件中的内容并将其转换为UTF-8。因此,如果文件已经包含垃圾,你只需要打一个"这是UTF-8"它上面有标签,但它仍然是垃圾。

这意味着您需要创建测试用例,该测试用例包含已知测试数据并将其移动到链的每个步骤:插入数据库,从数据库读取,写入CSV,写入文本文件,读取文件并下载给用户。

对于每个步骤,您需要编写单元测试,该单元测试采用已知的Unicode字符串(如abc öäü)并对其进行处理,然后检查结果。为了便于在Java代码中输入,请使用"abc \u00f6\u00e4\u00fc"您可能还希望在字符串的开头和结尾添加空格,以查看它们是否已正确保留。

file -i在这里没有多大帮助,因为它只是猜测文件包含的内容。文本文件中没有指示符(数据或元数据),表示"这是UTF-8"。 UTF-16支持BOM头,但几乎没有人使用UTF-16,因此很多工具都不支持(正确)。