溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解決Java編碼及網(wǎng)絡傳輸中的編碼問題

發(fā)布時間:2021-10-29 10:14:53 來源:億速云 閱讀:103 作者:柒染 欄目:編程語言

這篇文章給大家介紹如何解決Java編碼及網(wǎng)絡傳輸中的編碼問題,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

近來試著FTP搜索,遇到編碼問題,研究了下。

Java內(nèi)部的String為Unicode編碼,每個字符占兩個字節(jié)。

Java編解碼方法如下:

String str = "hi好啊me";  byte[] gbkBytes=str.getBytes("GBK");//將String的Unicode編碼轉為GBK編碼,輸出到字節(jié)中  String string=new String(gbkBytes,"GBK");//gbkBytes中的字節(jié)流以GBK方案解碼成Unicode形式的Java字符串

1、表單數(shù)據(jù)的編碼

現(xiàn)在的問題是,在網(wǎng)絡中,不知道客戶端發(fā)過來的字節(jié)流的編碼方案(發(fā)送前瀏覽器會對數(shù)據(jù)編碼?。?!各個瀏覽器還不一樣?。。。?/p>

解決方案如下:

如何解決Java編碼及網(wǎng)絡傳輸中的編碼問題

當然URLEncoder.encode(str, "utf-8")和URLDecoder.decode(strReceive,"utf-8")方法中的編碼方案要一致。

2、網(wǎng)址的編碼

但以上方法只適合表單數(shù)據(jù)的提交;對于URL則不行?。?!原因是URLEncoder把'/'也編碼了,瀏覽器發(fā)送時報錯?。?!那么,只要http://IP/子目錄把http://IP/這部分原封不動(當然這部分不要有中文),之后的數(shù)據(jù)以'/'分割后分段編碼即可。

代碼如下:

/**   * 對{@link URLEncoder#encode(String, String)}的封裝,但不編碼'/'字符,對其他字符分段編碼   *    * @param str   *            要編碼的URL   * @param encoding   *            編碼格式   * @return 字符串以字符'/'隔開,對每一段單獨編碼以encoding編碼格式編碼   * @version: 2012_01_10   *           <p>   *           注意:未考慮':',如直接對http://編解碼,會產(chǎn)生錯誤!?。≌堅谑褂们皩⑵浞蛛x出來,可以使用   *           {@link #encodeURLAfterHost(String, String)}方法解決此問題   *           <p>   *           注意:對字符/一起編碼,導致URL請求異常?。?nbsp;  */ public static String encodeURL(String str, String encoding) {      final char splitter = '/';      try {          StringBuilder sb = new StringBuilder(2 * str.length());          int start = 0;          for (int i = 0; i < str.length(); i++) {              if (str.charAt(i) == splitter) {                  sb.append(URLEncoder.encode(str.substring(start, i),                          encoding));                  sb.append(splitter);                  start = i + 1;              }          }          if (start < str.length())              sb.append(URLEncoder.encode(str.substring(start), encoding));          return sb.toString();      } catch (UnsupportedEncodingException e) {          e.printStackTrace();      }      return null;  }   /**   * 對IP地址后的URL通過'/'分割后進行分段編碼.   * <p>   * 對{@link URLEncoder#encode(String, String)}   * 的封裝,但不編碼'/'字符,也不編碼網(wǎng)站部分(如ftp://a.b.c.d/部分,檢測方法為對三個'/'字符的檢測,且要求前兩個連續(xù)),   * 對其他字符分段編碼   *    * @param str   *            要編碼的URL   * @param encoding   *            編碼格式   * @return IP地址后字符串以字符'/'隔開,對每一段單獨編碼以encoding編碼格式編碼,其他部分不變   * @version: 2012_01_10   *           <p>   *           注意:對字符/一起編碼,導致URL請求異常??!   */ public static String encodeURLAfterHost(String str, String encoding) {      final char splitter = '/';       int index = str.indexOf(splitter);//***個'/'的位置      index++;//移到下一位置??!      if (index < str.length() && str.charAt(index) == splitter) {//檢測***個'/'之后是否還是'/',如ftp://          index++;//從下一個開始          index = str.indexOf(splitter, index);//第三個'/';如ftp://anonymous:tmp@g.cn:219.223.168.20/中的***一個'/'          if (index > 0) {              return str.substring(0, index + 1)                      + encodeURL(str.substring(index + 1), encoding);//如ftp://anonymous:tmp@g.cn:219.223.168.20/天空          } else             return str;//如ftp://anonymous:tmp@g.cn:219.223.168.20      }       return encodeURL(str, encoding);   }   /**   * 對IP地址后的URL通過'/'分割后進行分段編碼.   * 此方法與{@link #decodeURLAfterHost(String, String)}配對使用   * @param str   *            要解碼的URL   * @param encoding   *            str的編碼格式   * @return IP地址后字符串以字符'/'隔開,對每一段單獨解碼以encoding編碼格式解碼,其他部分不變   * @version: 2012_01_10   *    *           <p>   *           注意:對字符/一起解碼,將導致URL請求異常??!   */ public static String decodeURLAfterHost(String str, String encoding) {      final char splitter = '/';      int index = str.indexOf(splitter);//***個'/'的位置      index++;//移到下一位置?。?nbsp;     if (index < str.length() && str.charAt(index) == splitter) {//檢測***個'/'之后是否還是'/',如ftp://          index++;//從下一個開始          index = str.indexOf(splitter, index);//第三個'/';如ftp://anonymous:tmp@g.cn:219.223.168.20/中的***一個'/'          if (index > 0) {              return str.substring(0, index + 1)                      + decodeURL(str.substring(index + 1), encoding);//如ftp://anonymous:tmp@g.cn:219.223.168.20/天空          } else             return str;//如ftp://anonymous:tmp@g.cn:219.223.168.20      }       return decodeURL(str, encoding);   }   /**   * 此方法與{@link #encodeURL(String, String)}配對使用   * <p>   * 對{@link URLDecoder#decode(String, String)}的封裝,但不解碼'/'字符,對其他字符分段解碼   *    * @param str   *            要解碼的URL   * @param encoding   *            str的編碼格式   * @return 字符串以字符'/'隔開,對每一段單獨編碼以encoding編碼格式解碼   * @version: 2012_01_10   *    *           <p>   *           注意:對字符/一起編碼,導致URL請求異常!!   */ public static String decodeURL(String str, String encoding) {      final char splitter = '/';      try {          StringBuilder sb = new StringBuilder(str.length());          int start = 0;          for (int i = 0; i < str.length(); i++) {              if (str.charAt(i) == splitter) {                  sb.append(URLDecoder.decode(str.substring(start, i),                          encoding));                  sb.append(splitter);                  start = i + 1;              }          }          if (start < str.length())              sb.append(URLDecoder.decode(str.substring(start), encoding));          return sb.toString();      } catch (UnsupportedEncodingException e) {          e.printStackTrace();      }      return null;  }

3、亂碼了還能恢復?

問題如下:

如何解決Java編碼及網(wǎng)絡傳輸中的編碼問題

貌似圖中的utf-8改成iso8859-1是可以的,utf-8在字符串中有中文時不行(但英文部分仍可正確解析)?。?!畢竟GBK的字節(jié)流對于utf-8可能是無效的,碰到無效的字符怎么解析,是否可逆那可不好說啊。

測試代碼如下:

package tests;   import java.io.UnsupportedEncodingException;  import java.net.URLEncoder;   /**   * @author LC   * @version: 2012_01_12   */ public class TestEncoding {      static String utf8 = "utf-8";      static String iso = "iso-8859-1";      static String gbk = "GBK";       public static void main(String[] args) throws UnsupportedEncodingException {          String str = "hi好啊me";          //      System.out.println("?的十六進制為:3F");          //      System.err          //              .println("出現(xiàn)中文時,如果編碼方案不支持中文,每個字符都會被替換為?的對應編碼?。ㄈ缭趇so-8859-1中)");          System.out.println("原始字符串:\t\t\t\t\t\t" + str);          String utf8_encoded = URLEncoder.encode(str, "utf-8");          System.out.println("用URLEncoder.encode()方法,并用UTF-8編碼后:\t\t" + utf8_encoded);          String gbk_encoded = URLEncoder.encode(str, "GBK");          System.out.println("用URLEncoder.encode()方法,并用GBK編碼后:\t\t" + gbk_encoded);          testEncoding(str, utf8, gbk);          testEncoding(str, gbk, utf8);          testEncoding(str, gbk, iso);          printBytesInDifferentEncoding(str);          printBytesInDifferentEncoding(utf8_encoded);          printBytesInDifferentEncoding(gbk_encoded);      }       /**       * 測試用錯誤的編碼方案解碼后再編碼,是否對原始數(shù)據(jù)有影響       *        * @param str       *            輸入字符串,Java的String類型即可       * @param encodingTrue       *            編碼方案1,用于模擬原始數(shù)據(jù)的編碼       * @param encondingMidian       *            編碼方案2,用于模擬中間的編碼方案       * @throws UnsupportedEncodingException       */     public static void testEncoding(String str, String encodingTrue,              String encondingMidian) throws UnsupportedEncodingException {          System.out.println();          System.out                  .printf("%s編碼的字節(jié)數(shù)據(jù)->用%s解碼并轉為Unicode編碼的JavaString->用%s解碼變?yōu)樽止?jié)流->讀入Java(用%s解碼)后變?yōu)镴ava的String\n",                          encodingTrue, encondingMidian, encondingMidian,                          encodingTrue);          System.out.println("原始字符串:\t\t" + str);          byte[] trueEncodingBytes = str.getBytes(encodingTrue);          System.out.println("原始字節(jié)流:\t\t" + bytesToHexString(trueEncodingBytes)                  + "\t\t//即用" + encodingTrue + "編碼后的字節(jié)流");          String encodeUseMedianEncoding = new String(trueEncodingBytes,                  encondingMidian);          System.out.println("中間字符串:\t\t" + encodeUseMedianEncoding + "\t\t//即用"                 + encondingMidian + "解碼原始字節(jié)流后的字符串");          byte[] midianBytes = encodeUseMedianEncoding.getBytes("Unicode");          System.out.println("中間字節(jié)流:\t\t" + bytesToHexString(midianBytes)                  + "\t\t//即中間字符串對應的Unicode字節(jié)流(和Java內(nèi)存數(shù)據(jù)一致)");          byte[] redecodedBytes = encodeUseMedianEncoding                  .getBytes(encondingMidian);          System.out.println("解碼字節(jié)流:\t\t" + bytesToHexString(redecodedBytes)                  + "\t\t//即用" + encodingTrue + "解碼中間字符串(流)后的字符串");          String restored = new String(redecodedBytes, encodingTrue);          System.out.println("解碼字符串:\t\t" + restored + "\t\t和原始數(shù)據(jù)相同?  "                 + restored.endsWith(str));      }       /**       * 將字符串分別編碼為GBK、UTF-8、iso-8859-1的字節(jié)流并輸出       *        * @param str       * @throws UnsupportedEncodingException       */     public static void printBytesInDifferentEncoding(String str)              throws UnsupportedEncodingException {          System.out.println("");          System.out.println("原始String:\t\t" + str + "\t\t長度為:" + str.length());          String unicodeBytes = bytesToHexString(str.getBytes("unicode"));          System.out.println("Unicode bytes:\t\t" + unicodeBytes);          String gbkBytes = bytesToHexString(str.getBytes("GBK"));          System.out.println("GBK bytes:\t\t" + gbkBytes);          String utf8Bytes = bytesToHexString(str.getBytes("utf-8"));          System.out.println("UTF-8 bytes:\t\t" + utf8Bytes);          String iso8859Bytes = bytesToHexString(str.getBytes("iso-8859-1"));          System.out.println("iso8859-1 bytes:\t" + iso8859Bytes + "\t\t長度為:"                 + iso8859Bytes.length() / 3);          System.out.println("可見Unicode在之前加了兩個字節(jié)FE FF,之后則每個字符兩字節(jié)");      }       /**       * 將該數(shù)組轉的每個byte轉為兩位的16進制字符,中間用空格隔開       *        * @param bytes       *            要轉換的byte序列       * @return 轉換后的字符串       */     public static final String bytesToHexString(byte[] bytes) {          StringBuilder sb = new StringBuilder(bytes.length * 2);          for (int i = 0; i < bytes.length; i++) {              String hex = Integer.toHexString(bytes[i] & 0xff);// &0xff是byte小于0時會高位補1,要改回0              if (hex.length() == 1)                  sb.append('0');              sb.append(hex);              sb.append(" ");          }          return sb.toString().toUpperCase();      }  }

關于如何解決Java編碼及網(wǎng)絡傳輸中的編碼問題就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI