最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】Android中,如何对某个编码(如GB2312)的字符串进行解码为Unicode字符

Android crifan 6822浏览 0评论

之前可以抓取网页的html了:

【已解决】Android中如何用代码实现去抓取网页

而且后来也确定,是获得了完整的html了:

【已解决】Android中,通过response.getEntity()去获得HttpClient返回的HttpResponse,只获得部分的HTML内容

现在接着要对获得的,GB2312编码的html,进行解码为对应的Unicode。


1.从:

How to Decode String in Android?

知道有个:

URLDecoder

2.然后找到android官网的:

URLDecoder

然后搜decode找到:

CharsetDecoder

3.后来也找到另外一个帖子:

CharsetDecoder.decode()与Charset.decode()

所以算了,直接去试试代码中,string是否有decode方法,结果没有找到。

4.参考:

关于Android解析Webservice数据乱码的问题

去试试:

String uniHtml = new String(respHtml, "GB2312");

结果也都是语法错误。

5.所以,看来,还是对于Android中的字符串编码的基本知识,不了解。

所以先去学习这方面的内容。

6.后来参考:

Android中文乱码彻底解决

看到了其处理办法,还是之前我就想到的,应该是读取stream,然后用对应编码解码为Unicode的string才对。

7.所以把之前的代码改为:

            	StringBuffer strBuf = new StringBuffer();
            	HttpEntity httpEnt = response.getEntity(); 
            	InputStream inputStream = httpEnt.getContent();
            	//String htmlCharset = "GB2312";
            	String htmlCharset = "GBK";
            	BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, htmlCharset));
            	String singleLine = "";
                while ((singleLine = br.readLine()) != null) {
                	strBuf.append(singleLine);
                }
                String respHtml = strBuf.toString();

但是有问题,会导致换行丢失了:

only single line resp html

所以,再去想办法,重新写个更好的处理。

8.后来自己无意间发现,EntityUtils.toString是可以给参数charset的,所以试了试:

            	String htmlCharset = "GBK";
            	String respHtml = EntityUtils.toString(response.getEntity(), htmlCharset);

然后就可以得到,完全的返回的html,且是Unicode的了:

EntityUtils.toString with charset can got unicode html

所以,至此,对于从HttpClient返回的response中,获得完整的,Unicode的html的事情,就已搞定了。

只是,对于,如果获得了GB2312的string,如果转换为Unicode的string,还是没有完成。

现在接着去折腾。

9.后来折腾了半天,随便试了试很多乱七八糟的代码:

            	
            	String htmlCharset = "GBK";
            	String respHtmlGbk = EntityUtils.toString(response.getEntity());
//            	ByteBuffer byteBuf = new ByteBuffer();
//            	Bytes gbkBytes = new Bytes();
//            	CharsetDecoder cd = new CharsetDecoder()
            	//String testStr = respHtmlGbk.getBytes(htmlCharset).toString();
            	
            	
            	StringBuffer sb = new StringBuffer();
            	sb.append(respHtmlGbk.toCharArray());
            	
            	String respHtml = new String(respHtmlGbk.getBytes(), htmlCharset);

结果的结论是:

Java中的String设计,和Python 3.x中类似:

String,本来就是已经是Unicode了。

对应的,某种编码的字符串,正常的话,应该是对应的bytes

所以才有类似于getBytes的函数,比如:

string getBytes using the named charset

对应写法是:

            	String htmlCharset = "GBK";
            	byte [] gbkByets = new byte[64*1024]; 
            	gbkByets = respHtml.getBytes(htmlCharset);

 

而此处,之前的方法,获得的一个字符串,实际上是一个有问题的字符串,

即应该是通过GBK解码,然后获得一个一个正常的字符串String;

但是由于没有指定编码,导致之前获得的String,实际上是使用系统默认的编码,Android中是UTF-8,

即,将本来是GBK的字符串,通过UTF-8去解码,然后得到了一个所谓的Unicode字符串,

所以,调试过程中,看到的中文部分,都是乱码。

正确解决办法就是之前所写的:

            	String htmlCharset = "GBK";
            	String respHtml = EntityUtils.toString(response.getEntity(), htmlCharset);

即在拿到返回的字符串的原始内容时,记得使用某种解码方式,传递正确的编码,然后将其解码为正确的Unicode字符串。

此处的respHtml才能是,正常的,不带乱码的,Unicode字符串。

 

【总结】

你第一时间,拿到的某个字符串String,自己要清楚是什么编码的。

然后用合适的办法,将其解码为对应的Unicode,最后得到的才是正常的Unicode的String。

 

比如,此处就是:

通过HttpClient获得的response,然后通过:

String htmlCharset = "GBK";
String respHtml = EntityUtils.toString(response.getEntity(), htmlCharset);

才能获得正确的,Unicode的String的。

如果写成:

String respHtml = EntityUtils.toString(response.getEntity());

那么,实际上是,把本来是GBK(GB2312)的html,使用系统默认的Utf-8去解码,此时的respHtml虽然也是Unicode的,但是是不正常的Unicode,其中的中文是乱码。

转载请注明:在路上 » 【已解决】Android中,如何对某个编码(如GB2312)的字符串进行解码为Unicode字符

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
83 queries in 0.201 seconds, using 22.06MB memory