Java csv中的字符编码
我们需要从Oracle DB表中提取数据,并将数据转储到csv文件和纯管道分隔的文本文件中。在应用程序上为用户提供链接,以便用户可以查看生成的csv/文本文件 由于需要进行大量的解析,所以我们编写了一个unixshell脚本,并从Struts/J2ee应用程序中调用它 早些时候,我们在生成的文件中丢失了中文和罗马字符,并且生成的文件具有us ascii字符集(使用->file-i选中)。后来我们使用了Java csv中的字符编码,java,unix,csv,encoding,utf-16le,Java,Unix,Csv,Encoding,Utf 16le,我们需要从Oracle DB表中提取数据,并将数据转储到csv文件和纯管道分隔的文本文件中。在应用程序上为用户提供链接,以便用户可以查看生成的csv/文本文件 由于需要进行大量的解析,所以我们编写了一个unixshell脚本,并从Struts/J2ee应用程序中调用它 早些时候,我们在生成的文件中丢失了中文和罗马字符,并且生成的文件具有us ascii字符集(使用->file-i选中)。后来我们使用了NLS_LANG=AMERICAN_AMERICA.AL32UTF8,这给了我们utf-8格式的
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();
如果我遗漏了任何细节,请告诉我。
感谢大家抽出时间来解决这个问题。与Unicode问题一样,转换链的每一步都必须完美工作。如果您在一个地方出错,数据将被默默地损坏。没有简单的方法可以确定它发生在哪里,您必须调试代码或编写单元测试 上述Java代码仅在文件实际包含UTF-8编码数据时有效;它不会“神奇地”找出文件中的内容并将其转换为UTF-8。因此,如果文件已经包含垃圾,您只需在其上贴上“this is UTF-8”标签,但它仍然是垃圾 这意味着您需要创建包含已知测试数据的测试用例,并将其移动到链的每个步骤:插入数据库、从数据库读取、写入CSV、写入文本文件、读取这些文件并下载给用户 对于每个步骤,您都需要编写单元测试,该测试采用一个已知的Unicode字符串,如
abcöäü
,并对其进行处理,然后检查结果。为了使Java代码更容易输入,请使用“abc\u00f6\u00e4\u00fc”您可能还希望在字符串的开头和结尾添加空格,以查看它们是否被正确保留
file-i
在这里帮不了你多少忙,因为它只是猜测文件包含什么。文本文件中没有表示“这是UTF-8”的指示符(数据或元数据)。UTF-16为此支持BOM头,但几乎没有人使用UTF-16,因此许多工具(正确地)不支持它。与Unicode问题一样,转换链的每一步都必须完美工作。如果您在一个地方出错,数据将被默默地损坏。没有简单的方法可以确定它发生在哪里,您必须调试代码或编写单元测试
上述Java代码仅在文件实际包含UTF-8编码数据时有效;它不会“神奇地”找出文件中的内容并将其转换为UTF-8。因此,如果文件已经包含垃圾,您只需在其上贴上“this is UTF-8”标签,但它仍然是垃圾
这意味着您需要创建包含已知测试数据的测试用例,并将其移动到链的每个步骤:插入数据库、从数据库读取、写入CSV、写入文本文件、读取这些文件并下载给用户
对于每个步骤,您都需要编写单元测试,该测试采用一个已知的Unicode字符串,如abcöäü
,并对其进行处理,然后检查结果。为了使Java代码更容易输入,请使用“abc\u00f6\u00e4\u00fc”您可能还希望在字符串的开头和结尾添加空格,以查看它们是否被正确保留
file-i
在这里帮不了你多少忙,因为它只是猜测文件包含什么。文本文件中没有表示“这是UTF-8”的指示符(数据或元数据)。UTF-16为此支持BOM头,但几乎没有人使用UTF-16,因此许多工具(正确地)不支持它。与Unicode问题一样,转换链的每一步都必须完美工作。如果您在一个地方出错,数据将被默默地损坏。没有简单的方法可以确定它发生在哪里,您必须调试代码或编写单元测试
上述Java代码仅在文件实际包含UTF-8编码数据时有效;它不会“神奇地”找出文件中的内容并将其转换为UTF-8。因此,如果文件已经包含垃圾,您只需在其上贴上“this is UTF-8”标签,但它仍然是垃圾
这意味着您需要创建包含已知测试数据的测试用例,并将其移动到链的每个步骤:插入数据库、从数据库读取、写入CSV、写入文本文件、读取这些文件并下载给用户
对于每个步骤,您都需要编写单元测试,该测试采用一个已知的Unicode字符串,如abcöäü
,并对其进行处理,然后检查结果。为了使Java代码更容易输入,请使用“abc\u00f6\u00e4\u00fc”您可能还希望在字符串的开头和结尾添加空格,以查看它们是否被正确保留
file-i
在这里帮不了你多少忙,因为它只是猜测文件包含什么。文本文件中没有表示“这是UTF-8”的指示符(数据或元数据)。UTF-16为此支持BOM头,但几乎没有人使用UTF-16,因此许多工具(正确地)不支持它。与Unicode问题一样,转换链的每一步都必须完美工作。如果你在一个地方出错,数据就会丢失
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();