现在的位置: 首页 > 综合 > 正文

android中关于文件解码时出现乱码的相关分析

2013年08月27日 ⁄ 综合 ⁄ 共 4374字 ⁄ 字号 评论关闭

以下分析主要是从针对ava层上的分析:

1. 在android中的播放器播放过程中,经常会出现歌曲列表,歌曲播放过程中相关信息出现乱码的情况。这里所说的乱码指的是在这些文件信息中经常会出现像“??。&&¥@”的这样的无效字符。造成这样的原因是:文件在记录信息的时候会使用一定的编码方式,像UTF-8,GBK,Big-5等等,这样的文件如果解析解码时使用的不是与之匹配的解码方式的,这样有些信息就是没有办法被解析解码到的,造成信息的遗漏解析,解码,更或者就是错的解析解码,这样,便出现了这里称之为乱码的错误信息。

     字符集(Charset):是一个系统支持的所有抽象字符的集合。字符是各种文,字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。

     字符编码(Character Encoding):是一套法则。是将我们自然的字符对应映射成计算机对应识别的数字对应,即就是把自然符号转换为计算机可以接受的数字系统的数,当然,这个数字是计算机的数字代码。

    例如,在计算机中,使用一个字节的大小来表示固定的一个自然字符,假设,“m“这个字符对应的是 00010101,这两者之间是一一对应的关系,这样的话,“m”就完成了字符编码的过程,当然这只是一个假设的例子,不属于任何一种编码方案。

  

    2. 有这样的一种说法:

    编码:字符集编码和字符编码方案的一个组合 ,它可以将字符集中的字符,映射成字节序列。编码隐含着编码字符集和字符编码方案,从而也隐含着字符集。就是说是两层含义。在UTF-8这样的编码中,首先明确的是UTF-8中有自己可以表示的自然字符集,每种不同的编码方式所能表示的字符的多少范围是不一样的。第二层,这样丰富的自然字符都有规定序列的数字构成一一对应的关系,这些数字是以字节为单位存储表示的。   

    UTF-8是一种编码,它是Unicode编码字符集和UTF8编码方案的一个组合。GB2312也是一种编码,它的编码字符集就是编码的简体中文字符集,编码方案采用定长编码。

    实践中经常混用编码字符集和编码这两个概念,这是因为大多数编码字符集都只有一种编码方案,这样的编码字符集(或者说编码)包括GB2312,GBK, ASCII, ISO8859-1等。

这里要注意的是,当编码字符集存在多种编码方案时,就有必要区分编码字符集和编码了,Unicode时一般是指编码字符集,说UTF-8UTF-16时才是指编码。

   3. 常见字符编码

    (1 )UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变。长度字符编码(定长码),也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部份修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。UTF-8使用一至四个字节为每个字符编码:在处理经常会用到的ASCII字符方面非常有效。在处理扩展的拉丁字符集方面也不比UTF-16差。对于中文字符来说,比UTF-32要好。

  ( 2)Big5码是一套双字节字符集,使用了双八码存储方法,以两个字节来安放一个字。第一个字节称为"高位字节",第二个字节称为"低位字节"。"高位字节"使用了0x81-0xFE,"低位字节"使用了0x40-0x7E,及0xA1-0xFE,Big5属中文内码,一般使用繁体中文(正体中文)。在Big5的分区中

   (3) Unicode(统一码、万国码、单一码、标准万国码)是业界的一种标准,它可以使电脑得以体现世界上数十种文字的系统。Unicode 是基于通用字符集(Universal Character Set)的标准来发展,并且同时也以书本的形式[1]对外发表。

  (4)等等还有其他的不在啰嗦。

4. java应用程序中对字符的解码:

    在音乐播放器中歌词部分的文件编码有对四种常见的编码格式 "GBK"、 "UTF-8"、"Unicode"、"UTF-16BE",每一种编码格式的区分在于写入文件头的信息不同。为了避免读取乱码的现象,在读取文本之前先读取文件头信息,以便做出正确的读取编码方式。

    public static String codeString(File file) throws Exception

   {

          BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file)); 

           int p = (bin.read() << 8) + bin.read();

          String code = null;

         Log.e("lyric","p="+p);

        switch (p)

        { 
           case 0xefbb:
           code = "UTF-8";             
             break;
           case 0xfffe: 
             code = "Unicode"; 

             break; 
           case 0xfeff: 

          code = "UTF-16BE";              
             break;
 default: 
             code = "GBK";

      
     return code; 

然后,以字符流的方式读取文本

 InputStream in = new FileInputStream(file);

br = new BufferedReader(new InputStreamReader(in, codeString(file)));

StringBuilder sb = new StringBuilder();

String temp = null;

while ((temp = br.readLine()) != null) {

sb.append(temp).append(" ");

}

 

5. 出现字符乱码的时候进行字符转换:java层的转换

    public class ChangeCharset {
    /** 8 位 UTF转换格式     */
public static final String UTF_8 = "UTF-8";

  /** 中文超大字符集     **/

public static final String GBK = "GBK";

/** 16 位 UTF转换格式,Big Endian(最低地址存放高位字节)字节顺序     */

public static final String UTF_16BE = "UTF-16BE";

/** 将字符编码转换成UTF-8     */

public String toUTF_8(String str) throws UnsupportedEncodingException {return this.changeCharset(str, UTF_8);}

/** 将字符编码转换成UTF-16BE     */

 public String toUTF_16BE(String str) throws UnsupportedEncodingException{return this.changeCharset(str, UTF_16BE);
    }
 /*

  * 字符串编码转换的实现方法
     * @param str    待转换的字符串
* @param newCharset    目标编码

  */
public String changeCharset(String str, String newCharset) throws UnsupportedEncodingException {

if(str != null) {

//用默认字符编码解码字符串。与系统相关,中文默认为GBK

    byte[] bs = str.getBytes();

return new String(bs, newCharset);    //用新的字符编码生成字符串

}
        return null;
 }

 

 /**
     
 * 字符串编码转换的实现方法
     * @param str    待转换的字符串
     * @param oldCharset    源字符集

     * @param newCharset    目标字符集

*/

 public String changeCharset(String str, String oldCharset, String newCharset)

throws UnsupportedEncodingException {

 if(str != null) {
            //用源字符编码解码字符串
byte[] bs = str.getBytes(oldCharset);

return new String(bs, newCharset);

 }
        return null;
}

 

public static void main(String[] args)throws UnsupportedEncodingException {

ChangeCharset test = new ChangeCharset();

String str = "This is a 中文的 String!";

System.out.println("str:" + str);

 String utf8 = test.toUTF_8(str);

System.out.println("转换成UTF-8码:" + utf8);

String utf16be = test.toUTF_16BE(str);

System.out.println("转换成UTF-16BE码:" + utf16be);

gbk = test.changeCharset(utf16be, UTF_16BE, GBK);

System.out.println("再把UTF-16BE编码的字符转换成GBK码:" + gbk);

}
}

输出结果:
              str:This is a 中文的 String!
            转换成UTF-8码:This is a ????? String!

            转换成UTF-16BE码:周楳?猠愠????瑲楮朡

            再把UTF-16BE编码的字符转换成GBK码:This is a 中文的 String!

 

原理分析:

1、调用String的getByte方法对字符串进行解码,得到字符串的字节数组。

2、根据字节数组和新的字符编码构造一个新的String对象,得到的就是按照新的字符编码生成的字符串.

(转发请注明转自:学PHP)  

抱歉!评论已关闭.