0

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

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

早些时候,我们在生成的文件中丢失了中文和罗马字符,生成的文件有 us-ascii 字符集(使用-> 文件 -i 进行检查)。后来我们使用 NLS_LANG=AMERICAN_AMERICA.AL32UTF8了,这给了我们 utf-8 格式的文件。

但是字符仍然是乱码,所以我们再次尝试了 iconv 命令并将 utf-8 文件转换为 utf-16le 字符集。 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();    

如果我错过了任何细节,请告诉我。感谢大家抽出时间来解决这个问题。

4

2 回答 2

2

能够解决它。首先,正如 Aaron 所提到的,删除了UTF-16LE编码以避免将来出现问题,并将文件编码为UTF-8. PrintWriter将Java 代码更改为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();
于 2014-12-30T09:32:08.487 回答
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,因此许多工具(正确地)不支持它。

于 2014-12-29T15:38:13.780 回答