2011-07-08 77 views
31
一个字符串是有效的UTF-8编码

我如何检查是否一个字符串是有效的UTF-8格式?检查是否在Java中

+5

你的意思是字节[]的有效编码? – bestsss

+0

最简单的事情可能是解码并重新编码。检查你得到同样的事情。几乎在每种情况下这都是正确的。 –

+0

@Peter不会总是有效,因为某些字符可以用不同的字节序列编码。两个字节序列都是正确的,并且对相同的字符进行编码,但字节不同。 – Jesper

回答

31

只有一个字节的数据可以进行检查。如果你构造了一个String,那么它已经在UTF-16内部。

另外字节数组可以是UTF-8编码。

这里是UTF-8转化的常见的情况。

String myString = "\u0048\u0065\u006C\u006C\u006F World"; 
System.out.println(myString); 
byte[] myBytes = null; 

try 
{ 
    myBytes = myString.getBytes("UTF-8"); 
} 
catch (UnsupportedEncodingException e) 
{ 
    e.printStackTrace(); 
    System.exit(-1); 
} 

for (int i=0; i < myBytes.length; i++) { 
    System.out.println(myBytes[i]); 
} 

如果你不知道你的字节数组的编码,juniversalchardet是一个库,以帮助您检测它。 https://docs.oracle.com/javase/tutorial/i18n/text/string.html

+4

就像澄清一样,String的一个实例不是UTF-16编码形式,严格来说,因为它允许不合格的代码单元序列(以隔离的代理单元形式)。但是,它是一个Unicode 16位字符串。 –

+4

更严格地说,Java String也不是真正的Unicode 16位字符串,因为它可以包含[surrogates](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/用于UCS4(3字节和4字节)字符的openjdk/6-b14/sun/nio/cs/Surrogate.java)。 – rustyx

+0

ICU4J是另一个Java库,可以帮助您检测字节数组的编码:http://site.icu-project.org/ –

1

以下职位由可在官方Java教程拍摄。

的字符串转换程序开始通过创建包含 Unicode字符的字符串:

String original = new String("A" + "\u00ea" + "\u00f1" + "\u00fc" + "C"); 

打印时,命名为原来的字符串显示为:

AêñüC 

到字符串对象转换为UTF -8,调用getBytes方法并且 指定适当的编码标识符作为参数。 getBytes方法返回UTF-8格式的字节数组。要从非Unicode字节的数组中创建 字符串对象,请使用编码参数调用字符串 构造函数。这使得这些 调用的代码被包含在try块,万一指定的编码是 不受支持:

try { 
    byte[] utf8Bytes = original.getBytes("UTF8"); 
    byte[] defaultBytes = original.getBytes(); 

    String roundTrip = new String(utf8Bytes, "UTF8"); 
    System.out.println("roundTrip = " + roundTrip); 
    System.out.println(); 
    printBytes(utf8Bytes, "utf8Bytes"); 
    System.out.println(); 
    printBytes(defaultBytes, "defaultBytes"); 
} catch (UnsupportedEncodingException e) { 
    e.printStackTrace(); 
} 

的字符串转换程序打印出在utf8Bytes值和 defaultBytes阵列展示了重要的一点:转换后的文本的长度可能与源 文本的长度不同。某些Unicode字符转换为单个字节,其他转换为 对或三字节的字节。 的printBytes方法通过调用byteToHex方法,它是在源文件中所定义, UnicodeFormatter.java显示字节数组。这里是printBytes方法:

public static void printBytes(byte[] array, String name) { 
    for (int k = 0; k < array.length; k++) { 
     System.out.println(name + "[" + k + "] = " + "0x" + 
      UnicodeFormatter.byteToHex(array[k])); 
    } 
} 

printBytes方法的输出如下。请注意,只有第一 和最后一个字节,A和C的人物,都是一样的在两个数组:

utf8Bytes[0] = 0x41 
utf8Bytes[1] = 0xc3 
utf8Bytes[2] = 0xaa 
utf8Bytes[3] = 0xc3 
utf8Bytes[4] = 0xb1 
utf8Bytes[5] = 0xc3 
utf8Bytes[6] = 0xbc 
utf8Bytes[7] = 0x43 
defaultBytes[0] = 0x41 
defaultBytes[1] = 0xea 
defaultBytes[2] = 0xf1 
defaultBytes[3] = 0xfc 
defaultBytes[4] = 0x43