cam*_*mbo 11 java character-encoding
我在将一些法语文本转换为UTF8时遇到了一些问题,因此可以在控制台,文本文件或GUI元素中正确显示.
原始字符串是
HANDICAP╔ES
应该是
HANDICAPÉES
这是一个代码片段,显示了我如何使用jackcess Database驱动程序读取Eclipse/Linux环境中的Acccess MDB文件.
Database database = Database.open(new File(filepath));
Table table = database.getTable(tableName, true);
Iterator rowIter = table.iterator();
while (rowIter.hasNext()) {
Map<String, Object> row = this.rowIter.next();
// convert fields to UTF
Map<String, Object> rowUTF = new HashMap<String, Object>();
try {
for (String key : row.keySet()) {
Object o = row.get(key);
if (o != null) {
String valueCP850 = o.toString();
// String nameUTF8 = new String(valueCP850.getBytes("CP850"), "UTF8"); // does not work!
String valueISO = new String(valueCP850.getBytes("CP850"), "ISO-8859-1");
String valueUTF8 = new String(valueISO.getBytes(), "UTF-8"); // works!
rowUTF.put(key, valueUTF8);
}
}
} catch (UnsupportedEncodingException e) {
System.err.println("Encoding exception: " + e);
}
}
Run Code Online (Sandbox Code Playgroud)
在代码中,您将看到我想直接转换为UTF8的位置,这似乎不起作用,因此我必须进行双重转换.另请注意,使用jackcess驱动程序时似乎没有办法指定编码类型.
谢谢,Cam
基于新信息的新分析.
看起来您的问题在于文本在存储在Access DB中之前的编码.它似乎已编码为ISO-8859-1或windows-1252,但解码为cp850,导致字符串HANDICAP?ES存储在DB中.
正确地从数据库中检索到该字符串后,您现在正在尝试反转原始编码错误并恢复应该存储的字符串:HANDICAPÉES.你用这条线完成了这个:
String valueISO = new String(valueCP850.getBytes("CP850"), "ISO-8859-1");
Run Code Online (Sandbox Code Playgroud)
getBytes("CP850")将字符?转换为字节值0xC9,并且String构造函数根据ISO-8859-1对其进行解码,从而生成字符É.下一行:
String valueUTF8 = new String(valueISO.getBytes(), "UTF-8");
Run Code Online (Sandbox Code Playgroud)
...什么也没做. getBytes()使用平台默认编码对字符串进行编码,该编码在Linux系统上为UTF-8.然后,String构造函数使用相同的编码对其进行解码.删除该行,您仍然应该得到相同的结果.
更重要的是,您尝试创建"UTF-8字符串"是错误的.您不需要关心Java字符串的编码 - 它们总是UTF-16.将文本带入Java应用程序时,您只需确保使用正确的编码对其进行解码.
如果我的分析正确,您的Access驱动程序正在正确解码它; 问题出在另一端,可能是在DB进入图片之前. 这就是你需要解决的问题,因为new String(getBytes())在所有情况下都不能指望黑客行事.
原始分析,基于没有信息.: - /
如果你在HANDICAP?ES控制台上看到,可能没问题.鉴于此代码:
System.out.println("HANDICAPÉES");
Run Code Online (Sandbox Code Playgroud)
在将(Unicode)字符串发送到控制台之前,它将(Unicode)字符串转换为平台默认编码windows-1252.然后控制台使用自己的默认编码解码,恰好是cp850.所以控制台显示错误,但这是正常的.如果要正确显示,可以使用以下命令更改控制台的编码:
CHCP 1252
Run Code Online (Sandbox Code Playgroud)
要在GUI元素(如JLabel)中显示字符串,您不必执行任何特殊操作.只要确保使用可以显示所有字符的字体,但这对法语来说应该不是问题.
至于写入文件,只需在创建Writer时指定所需的编码:
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("myFile.txt"), "UTF-8");
Run Code Online (Sandbox Code Playgroud)
String s = "HANDICAP?ES";
System.out.println(new String(s.getBytes("CP850"), "ISO-8859-1")); // HANDICAPÉES
Run Code Online (Sandbox Code Playgroud)
这显示正确的字符串值.这意味着它最初使用ISO-8859-1进行编码/解码,然后使用CP850进行了错误编码(最初CP1252也称为Windows ANSI,如注释中所指出的那样确实也是可能的,因为它具有与ISO-8859-1中相同的代码点).É
对齐环境和二进制管道以使用所有同一个字符编码.你不能也不应该在它们之间进行转换.您可能会以这种方式丢失非ASCII范围内的信息.
注意:请勿使用上面的代码片段来"修复"问题!那不是正确的解决方案.
更新:你显然仍在努力解决这个问题.我将重复答案的重要部分:
调整你的环境,二元管道使用所有的一个和相同的字符编码.
你可以不,应该不是他们之间的转换.您可能会以这种方式丢失非ASCII范围内的信息.
千万不要使用上面的代码片段,以"修复"的问题!那不是正确的解决方案.
要解决此问题,您需要选择要在整个应用程序中使用的字符编码X. 我建议UTF-8.更新MS Access以使用编码X.更新开发环境以使用编码X.更新java.io代码中的读取器和编写器以使用编码X.更新编辑器以使用编码X读取/写入文件.更新应用程序的用户界面以使用编码十,不要没有在某个步骤中使用Y或Z或什么的.如果某些数据存储区(MS Access,文件等)中的字符已损坏,则需要通过手动替换数据存储区中的字符来修复它.不要为此使用Java.
如果您实际上使用"命令提示符"作为用户界面,那么您实际上已经丢失了.它不支持UTF-8.正如评论和评论中链接的文章中所建议的那样,您需要创建一个Swing应用程序,而不是依赖于受限制的命令提示符环境.
| 归档时间: |
|
| 查看次数: |
49566 次 |
| 最近记录: |