在去年写一个 joke 随即的时候,我写了一个爬虫在我的服务器,我用代码把获取的 joke 数据排成了一个有序的txt文本,这是我
需要远程读取这个txt文本数据,需要外部访问里面的 joke 数据,遇到读取的时候第一行代码首位字符出现“?”乱码的情况,刚开
始以为是 “\u000000” 导致的,print 发现是我想错了,后来想到通过打印byte来解决,才最终搞定,今天在写 150多家快递查询
的时候,我需要把我自己写好的服务器 txt 快递商家读取,并且封装成 xml 或者 json 供自己使用,又遇到这样的问题,所以觉得
有必要分享一下解决办法以及这个问题的原因所在。
通过java写的UTF-8文件,可以获取文件里面本身的数据,但是如果用记事本将相同的内容使用UTF-8格式保存,则在使用程序读
取是会从文件中多读出一个不可见字符,这个字符在 console 是以 “?”形式出现的,究其原因可能是 Java在 处理UTF-8 bom
编码文件的时候有 bug,JDK 1.5.-1.7 都有出现,博主的是 1.7,我们可以这样来规避这样的问题,就是采用 byte 来重组我们的
bytes 最后重新组合成我们的内容
下面来看一个案例剖析:
原始为处理例子:
public static void HttpRequest(String Request){ StringBuffer buffer = new StringBuffer(); try { URL url = new URL(Request); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(false); connection.setRequestMethod("GET"); InputStream input = connection.getInputStream(); InputStreamReader read = new InputStreamReader(input,"UTF-8"); BufferedReader reader = new BufferedReader(read); String line; while((line=reader.readLine())!=null){ buffer.append(line); } String lines = buffer.toString(); byte[] allbytes = lines.getBytes("UTF-8"); for (int i=0; i < allbytes.length; i++) { if(i==0){ System.out.print("原始未打乱重排字节数组,长度"+allbytes.length+":"); } int tmp = allbytes[i]; String hexString = Integer.toHexString(tmp); // 将每一个 byte to 十六进制,去除前2位,即0x 取后面的2位表示 hexString = hexString.substring(hexString.length() -2); // 空格分离, 大写区分区别 System.out.print(" "+hexString.toUpperCase()); } System.out.println("\n"+new String(allbytes,"utf-8")+"\n"); reader.close(); read.close(); input.close(); input = null; connection.disconnect(); } catch (Exception e) { } }
处理后的例子:
public static void HttpRequest2(String Request){ JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); try { URL url = new URL(Request); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(false); connection.setRequestMethod("GET"); InputStream input = connection.getInputStream(); InputStreamReader read = new InputStreamReader(input,"UTF-8"); BufferedReader reader = new BufferedReader(read); String line; while((line=reader.readLine())!=null){ buffer.append(line); } String lines = buffer.toString(); byte[] allbytes = lines.getBytes("UTF-8"); byte[] new_allbytes = new byte[allbytes.length-3]; for (int i=0; i < allbytes.length; i++) { // 截掉乱码的字节,从第三个字节开始读取,并且重组它们 // 下标从第三个开始,所以i-3,意为着原始字节数组的索引3 // 也就是第四位作为重组后的第一个索引,以此类推 if(i>=3){ // 将每一个 byte to 十六进制,去除前2位,即0x 取后面的2位表示 if(i-3==0){ System.out.print("\n经过打乱重排的字节数组,长度"+new_allbytes.length+":"); } new_allbytes[i-3] = allbytes[i]; int temp = new_allbytes[i-3]; String result = Integer.toHexString(temp); result = result.substring(result.length()-2); // 空格分离,大写区分区别 System.out.print(" "+result.toUpperCase()); } } System.out.print("\n"+new String(new_allbytes,"utf-8")); reader.close(); read.close(); input.close(); input = null; connection.disconnect(); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (Exception e) { } }
执行:
执行结果对比: