Java;尝试将包含ISO-8859-1编码的字符串转换为UTF-8,但文件是UTF-8。

3

我不知道这是否有意义,但这就是我的看法。

我正在使用Eclipse编写文件,并为所有文件使用UTF-8编码。在其中一个文件中,我需要将一个字符串从ISO-8859-1转换为UTF-8。但是,该字符串是在文件内部形成的(而不是来自输入),这就是我认为我的字符串最初以UTF-8格式开始,而转换并没有按照我预期的方式进行的原因。

该字符串的原始内容如下:

||3.2|2013-01-25T17:24:00|ingreso|PAGO EN UNA SOLA EXHIBICION|6386.21|MXN|7408.00|No identificado|NAUCALPAN DE JUÁREZ, ESTADO DE MEXICO|CAOS640116HT5|OSCAR MARTIN CARRERA|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JUÁREZ|ESTADO DE MEXICO|MÉXICO|53100|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JUÁREZ|ESTADO DE MEXICO|MÉXICO|53100|Persona Física con Actividad Empresarial|BAÑ930616R66|BAÑOMOBIL, S.A. DE C.V.|Av. 1° de Mayo|197|San. Lorenzo|TLALNEPANTLA DE BAZ|ESTADO DE MEXICO|MÉXICO|54047|1|NO APLICA|Dominio .com|Dominio por 1 año www.sanitariosportatiles.com|586.21|586.21|1|NO APLICA|Hospedaje 2 Gb|Hospedaje 2 Gb por 1 año www.sanitariosportatiles.com|5800.00|5800.00|IVA|16.00|1021.79|1021.79||

应该使用ISO-8859-1作为原始编码,当我将其转换为UTF-8时,它应该生成。

||3.2|2013-01-25T17:05:06|ingreso|PAGO EN UNA SOLA EXHIBICION|6386.21|MXN|7408.00|No identificado|NAUCALPAN DE JUÃREZ, ESTADO DE MEXICO|CAOS640116HT5|OSCAR MARTIN CARRERA|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JUÃREZ|ESTADO DE MEXICO|MÉXICO|53100|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JUÃREZ|ESTADO DE MEXICO|MÉXICO|53100|Persona Física con Actividad Empresarial|BAÑ930616R66|BAÑOMOBIL, S.A. DE C.V.|Av. 1° de Mayo|197|San. Lorenzo|TLALNEPANTLA DE BAZ|ESTADO DE MEXICO|MÉXICO|54047|1|NO APLICA|Dominio .com|Dominio por 1 año www.sanitariosportatiles.com|586.21|586.21|1|NO APLICA|Hospedaje 2 Gb|Hospedaje 2 Gb por 1 año www.sanitariosportatiles.com|5800.00|5800.00|IVA|16.00|1021.79|1021.79||

这正是我需要的,但我还没有实现它。

以下是我迄今为止尝试过的。

    String input = null;
    input = "||3.2|2013-01-25T17:24:00|ingreso|PAGO EN UNA SOLA EXHIBICION|6386.21|MXN|7408.00|No identificado|NAUCALPAN DE JUÁREZ, ESTADO DE MEXICO|CAOS640116HT5|OSCAR MARTIN CARRERA|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JUÁREZ|ESTADO DE MEXICO|MÉXICO|53100|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JUÁREZ|ESTADO DE MEXICO|MÉXICO|53100|Persona Física con Actividad Empresarial|BAÑ930616R66|BAÑOMOBIL, S.A. DE C.V.|Av. 1° de Mayo|197|San. Lorenzo|TLALNEPANTLA DE BAZ|ESTADO DE MEXICO|MÉXICO|54047|1|NO APLICA|Dominio .com|Dominio por 1 año www.sanitariosportatiles.com|586.21|586.21|1|NO APLICA|Hospedaje 2 Gb|Hospedaje 2 Gb por 1 año www.sanitariosportatiles.com|5800.00|5800.00|IVA|16.00|1021.79|1021.79||";
    String intento1 = null, intento2 = null, intento3 = null;
    try {
        intento1 = new String(input.getBytes("ISO-8859-1"),"UTF-8");
        intento2 = new String(intento1.getBytes(), "UTF-8");
        intento3 = new String(input.getBytes(),"UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    System.out.println(intento1);
    System.out.println(intento2); 
    System.out.println(intento3);   

这将返回

||3.2|2013-01-25T17:24:00|ingreso|PAGO EN UNA SOLA EXHIBICION|6386.21|MXN|7408.00|No identificado|NAUCALPAN DE JU?REZ, ESTADO DE MEXICO|CAOS640116HT5|OSCAR MARTIN CARRERA|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JU?REZ|ESTADO DE MEXICO|M?XICO|53100|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JU?REZ|ESTADO DE MEXICO|M?XICO|53100|Persona F?sica con Actividad Empresarial|BA?930616R66|BA?OMOBIL, S.A. DE C.V.|Av. 1? de Mayo|197|San. Lorenzo|TLALNEPANTLA DE BAZ|ESTADO DE MEXICO|M?XICO|54047|1|NO APLICA|Dominio .com|Dominio por 1 a?o www.sanitariosportatiles.com|586.21|586.21|1|NO APLICA|Hospedaje 2 Gb|Hospedaje 2 Gb por 1 a?o www.sanitariosportatiles.com|5800.00|5800.00|IVA|16.00|1021.79|1021.79||
||3.2|2013-01-25T17:24:00|ingreso|PAGO EN UNA SOLA EXHIBICION|6386.21|MXN|7408.00|No identificado|NAUCALPAN DE JU?REZ, ESTADO DE MEXICO|CAOS640116HT5|OSCAR MARTIN CARRERA|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JU?REZ|ESTADO DE MEXICO|M?XICO|53100|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JU?REZ|ESTADO DE MEXICO|M?XICO|53100|Persona F?sica con Actividad Empresarial|BA?930616R66|BA?OMOBIL, S.A. DE C.V.|Av. 1? de Mayo|197|San. Lorenzo|TLALNEPANTLA DE BAZ|ESTADO DE MEXICO|M?XICO|54047|1|NO APLICA|Dominio .com|Dominio por 1 a?o www.sanitariosportatiles.com|586.21|586.21|1|NO APLICA|Hospedaje 2 Gb|Hospedaje 2 Gb por 1 a?o www.sanitariosportatiles.com|5800.00|5800.00|IVA|16.00|1021.79|1021.79||
||3.2|2013-01-25T17:24:00|ingreso|PAGO EN UNA SOLA EXHIBICION|6386.21|MXN|7408.00|No identificado|NAUCALPAN DE JU?REZ, ESTADO DE MEXICO|CAOS640116HT5|OSCAR MARTIN CARRERA|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JU?REZ|ESTADO DE MEXICO|M?XICO|53100|CTO. ORADORES 33|33|CD. SATELITE|NAUCALPAN DE JU?REZ|ESTADO DE MEXICO|M?XICO|53100|Persona F?sica con Actividad Empresarial|BA?930616R66|BA?OMOBIL, S.A. DE C.V.|Av. 1? de Mayo|197|San. Lorenzo|TLALNEPANTLA DE BAZ|ESTADO DE MEXICO|M?XICO|54047|1|NO APLICA|Dominio .com|Dominio por 1 a?o www.sanitariosportatiles.com|586.21|586.21|1|NO APLICA|Hospedaje 2 Gb|Hospedaje 2 Gb por 1 a?o www.sanitariosportatiles.com|5800.00|5800.00|IVA|16.00|1021.79|1021.79||

这并不是我想要的。

编辑1:当我从输入中获取字符串时,其中一个转换可以正常工作,但我需要它在文件内声明时也能正常工作。

编辑2:基本上我需要的是 http://cryptosys.net/cgi-bin/manual.cgi?m=pki&name=CNV_UTF8FromLatin1 但是用Java实现。

4个回答

9

简单来说,如果你想将字符集 charset=iso-8859-1 转换成 Java 字符串(默认为 UTF-8),以下是步骤:

 String response= new String(input.getBytes("ISO-8859-1"),"UTF-8");

4

我终于按照问题中指定的方式展示了它,只是我使用了错误的字符集。

intento2 = new String(input.getBytes(Charset.forName("UTF-8")), Charset.forName("Windows-1252"));

我需要按照我的要求来显示它。


2
我认为这里的根本问题在于你的期望。如果我理解正确,你希望通过更改字符编码将Á更改为Ã。这是不可能的。它们是不同的字符;即不同的代码点- Á是Unicode代码点00C1(或ISO-8859-1中的C1),而Ã是00C3 / C3。
因此,当您将ISO-8859-1中的Á转换为Unicode再转换为UTF-8时,您应该得到完全相同的字符Á。如果不是这样,那么翻译就会出现问题。
如果您的语言/地区的词汇规则表明ÁÃ实际上是等效的,则将其“标准化”为首选形式是合理的。但是,字符编码/解码的作用并不是进行这种与语言环境相关的翻译。您需要自己编写代码...或找到其他库来执行此操作。
在字节级别胡闹(使用一种字符集进行编码,使用另一种字符集进行解码)不会“修复”此问题。如果有什么,它只会使情况变得更糟。您的胡闹正在生成无法映射到目标编码方案的字节序列...因此出现了问号。

问题是,当我从输入源获取它时,例如将其粘贴到命令行中而不是在文件内声明它时,我确实得到了期望的结果。我知道我需要实现的目标似乎很奇怪,但这是另一个服务的要求,所以我需要它以这种方式运行,并且我认为字符集编码和解码会起到作用,某种程度上它确实起到了作用(我只能通过输入源实现它),但我无法在文件内完成它。 - alexhg11
@alexhg11 - 我相信你需要编写Java代码来根据你的要求翻译单个字符。 (但是MÉXICO的翻译是真实的吗?在我的浏览器中看起来很奇怪...) - Stephen C
显然,这对我来说也太奇怪了,但这就是 WebService 所要求的方式,而这正是我遇到困难的地方 :/。我该如何处理呢?我需要在字节级别上进行操作吗? - alexhg11

0

在从二进制表示中加载任何数据时,您必须知道用于该表示的编码方式,以便解释或解码它。如果您假设错误的编码方式,则可能会得到垃圾--一些毫无意义的东西。

为了从二进制数据构造字符串,您必须指定源数据的编码方式。否则,您可能会得到垃圾--构造的字符串可能不包含源数据中表示的字符。

更具体地说,对于您的情况,如果您尝试使用ISO-8859-1编码加载UTF-8数据,则可能会得到垃圾。我说“可能”是因为这两种编码实际上有很多重叠:低127个代码点(如果我记得正确)。如果仅使用这些低127个代码点,则解码实际上可能“有效”,但由于这不能保证,因此不应依赖它。

如果您告诉Eclipse使用UTF-8解码您的源文件,则只应使用能够并配置为使用UTF-8编码进行编辑的编辑器编辑这些源文件。

另外需要注意的一点是:Java中字符串数据的内部表示形式是UTF-16。因此,说你有包含ISO-8859-1编码的字符串是不正确的。如果你有一个字符串,那么它总是包含UTF-16数据。这些数据是否正确取决于你如何构造字符串,正如上面所讨论的那样。

我不相信Java中的String数据的内部表示是UTF-8。 - Samuel Edwin Ward
哦,我的错。它们是UTF-16编码。:) 但是,它们不是ISO-8859-1编码。 - JimN
有没有一种方法可以声明不同编码的字符串? - alexhg11
我再重复一遍:Java字符串在内部使用UTF-16编码。当从字符数据构建Java字符串时,您可以指定要使用的编码以进行转换为内部的UTF-16编码。 - JimN
你可能想把所有本地化字符串放在一个单独的数据文件中(而不是粘贴到Java源文件中),然后在运行时加载该数据文件,使用创建/编辑文件时使用的相同编码。查看java.util.Properties以便以一种方便的方式将键/值对存储在文件中。在加载文件时,使用允许您指定要使用的编码的Reader。例如:new InputStreamReader(new FileInputStream(file), "ISO-8859-1")。出于部署目的,将数据作为资源而不是文件加载可能更容易。 - JimN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接