在 Java 中将 UTF-8 转换为 ISO-8859-1 - 如何将其保持为单字节

Posted

技术标签:

【中文标题】在 Java 中将 UTF-8 转换为 ISO-8859-1 - 如何将其保持为单字节【英文标题】:Converting UTF-8 to ISO-8859-1 in Java - how to keep it as single byte 【发布时间】:2010-10-13 22:37:32 【问题描述】:

我正在尝试将用 Java 编码的 UTF-8 字符串转换为 ISO-8859-1。例如,在字符串 'âabcd' 中,'â' 在 ISO-8859-1 中表示为 E2。在 UTF-8 中,它表示为两个字节。 C3 A2 我相信。当我执行 getbytes(encoding) 然后使用 ISO-8859-1 编码中的字节创建一个新字符串时,我得到两个不同的字符。 ¢。有没有其他方法可以做到这一点,以保持字符相同,即 âabcd?

【问题讨论】:

【参考方案1】:

如果您处理的是 UTF-16 以外的字符编码,则不应使用 java.lang.Stringchar 原语 - 您应该只使用 byte[] 数组或 ByteBuffer 对象。然后,您可以使用java.nio.charset.Charset 进行编码之间的转换:

Charset utf8charset = Charset.forName("UTF-8");
Charset iso88591charset = Charset.forName("ISO-8859-1");

ByteBuffer inputBuffer = ByteBuffer.wrap(new byte[](byte)0xC3, (byte)0xA2);

// decode UTF-8
CharBuffer data = utf8charset.decode(inputBuffer);

// encode ISO-8559-1
ByteBuffer outputBuffer = iso88591charset.encode(data);
byte[] outputData = outputBuffer.array();

【讨论】:

好点,虽然我建议使用缓冲区可能并不总是最方便的方法。基本的InputStreamOutputStream(带有适当的包装 Readers、Writers)有时更有用,并且不需要将整个内容保存在内存中。但是哪个更方便当然取决于用例。【参考方案2】:
byte[] iso88591Data = theString.getBytes("ISO-8859-1");

会成功的。根据您的描述,您似乎正在尝试“存储 ISO-8859-1 字符串”。 Java 中的字符串对象总是以 UTF-16 隐式编码。无法更改该编码。

你可以做的,'虽然是获取构成它的其他编码的字节(使用如上所示的.getBytes()方法)。

【讨论】:

【参考方案3】:

从一组使用 UTF-8 对字符串进行编码的字节开始,从该数据创建一个字符串,然后获取一些以不同编码对字符串进行编码的字节:

    byte[] utf8bytes =  (byte)0xc3, (byte)0xa2, 0x61, 0x62, 0x63, 0x64 ;
    Charset utf8charset = Charset.forName("UTF-8");
    Charset iso88591charset = Charset.forName("ISO-8859-1");

    String string = new String ( utf8bytes, utf8charset );

    System.out.println(string);

    // "When I do a getbytes(encoding) and "
    byte[] iso88591bytes = string.getBytes(iso88591charset);

    for ( byte b : iso88591bytes )
        System.out.printf("%02x ", b);

    System.out.println();

    // "then create a new string with the bytes in ISO-8859-1 encoding"
    String string2 = new String ( iso88591bytes, iso88591charset );

    // "I get a two different chars"
    System.out.println(string2);

这会正确输出字符串和 iso88591 字节:

âabcd 
e2 61 62 63 64 
âabcd

所以你的字节数组没有与正确的编码配对:

    String failString = new String ( utf8bytes, iso88591charset );

    System.out.println(failString);

输出

âabcd

(或者,或者您只是将 utf8 字节写入文件并在其他地方读取为 iso88591)

【讨论】:

【参考方案4】:

这是我需要的:

public static byte[] encode(byte[] arr, String fromCharsetName) 
    return encode(arr, Charset.forName(fromCharsetName), Charset.forName("UTF-8"));


public static byte[] encode(byte[] arr, String fromCharsetName, String targetCharsetName) 
    return encode(arr, Charset.forName(fromCharsetName), Charset.forName(targetCharsetName));


public static byte[] encode(byte[] arr, Charset sourceCharset, Charset targetCharset) 

    ByteBuffer inputBuffer = ByteBuffer.wrap( arr );

    CharBuffer data = sourceCharset.decode(inputBuffer);

    ByteBuffer outputBuffer = targetCharset.encode(data);
    byte[] outputData = outputBuffer.array();

    return outputData;

【讨论】:

【参考方案5】:

如果你在字符串中有正确的编码,你不需要做更多的事情来获取另一个编码的字节。

public static void main(String[] args) throws Exception 
    printBytes("â");
    System.out.println(
            new String(new byte[]  (byte) 0xE2 , "ISO-8859-1"));
    System.out.println(
            new String(new byte[]  (byte) 0xC3, (byte) 0xA2 , "UTF-8"));


private static void printBytes(String str) 
    System.out.println("Bytes in " + str + " with ISO-8859-1");
    for (byte b : str.getBytes(StandardCharsets.ISO_8859_1)) 
        System.out.printf("%3X", b);
    
    System.out.println();
    System.out.println("Bytes in " + str + " with UTF-8");
    for (byte b : str.getBytes(StandardCharsets.UTF_8)) 
        System.out.printf("%3X", b);
    
    System.out.println();

输出:

Bytes in â with ISO-8859-1
 E2
Bytes in â with UTF-8
 C3 A2
â
â

【讨论】:

【参考方案6】:

对于文件编码...

public class FRomUtf8ToIso 
        static File input = new File("C:/Users/admin/Desktop/pippo.txt");
        static File output = new File("C:/Users/admin/Desktop/ciccio.txt");


    public static void main(String[] args) throws IOException 

        BufferedReader br = null;

        FileWriter fileWriter = new FileWriter(output);
        try 

            String sCurrentLine;

            br = new BufferedReader(new FileReader( input ));

            int i= 0;
            while ((sCurrentLine = br.readLine()) != null) 
                byte[] isoB =  encode( sCurrentLine.getBytes() );
                fileWriter.write(new String(isoB, Charset.forName("ISO-8859-15") ) );
                fileWriter.write("\n");
                System.out.println( i++ );
            

         catch (IOException e) 
            e.printStackTrace();
         finally 
            try 
                fileWriter.flush();
                fileWriter.close();
                if (br != null)br.close();
             catch (IOException ex) 
                ex.printStackTrace();
            
        

    


    static byte[] encode(byte[] arr)
        Charset utf8charset = Charset.forName("UTF-8");
        Charset iso88591charset = Charset.forName("ISO-8859-15");

        ByteBuffer inputBuffer = ByteBuffer.wrap( arr );

        // decode UTF-8
        CharBuffer data = utf8charset.decode(inputBuffer);

        // encode ISO-8559-1
        ByteBuffer outputBuffer = iso88591charset.encode(data);
        byte[] outputData = outputBuffer.array();

        return outputData;
    


【讨论】:

【参考方案7】:

除了亚当·罗森菲尔德的回答,我想补充一点,ByteBuffer.array() 返回缓冲区的底层字节数组,不一定要“修剪”到最后一个字符。需要额外的操作,例如this答案中提到的那些;特别是:

byte[] b = new byte[bb.remaining()]
bb.get(b);

【讨论】:

【参考方案8】:

驱逐非 ISO-8859-1 字符,将被替换为 '?' (例如发送到 ISO-8859-1 数据库之前):

utf8String = new String (utf8String.getBytes(), "ISO-8859-1" );

【讨论】:

? 替换所有非 ASCII 字符似乎是一个糟糕的解决方案,因为它可以在不丢失字符串的情况下进行转换。 @s4y 你是对的,这似乎是一个糟糕的解决方案,但想想 ASCII。您根本不能在 ASCII 中使用变音符号。您将不得不对无法编码的字符进行something。对于手头的问题,这是最简单且正确的解决方案。可以考虑使用 StandardCharsets.ISO_8859_1。 @fahrradfahrer 对于它的价值,如果我今天写那条评论,我就不会使用“可怕”这个词!但对于这种情况,我可能会选择***.com/a/14121678/84745 之类的东西,它本质上为您提供了 ASCII 字符串的近似值。

以上是关于在 Java 中将 UTF-8 转换为 ISO-8859-1 - 如何将其保持为单字节的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中将 UTF-8 转换为 US-Ascii

在Java(JSP)中将十进制NCR代码转换为UTF-8

在java中将带有命名空间的xml转换为json

如何在 Python 中将文件转换为 utf-8?

在 Java 中将 HTML 字符代码转换为 char

如何在 Python 中将字符串转换为 utf-8