java 檢測文本、文件編碼

jopen 9年前發布 | 2K 次閱讀 Java

/**

 * 默認GB18030
 */
public static final String detectCharset(byte[] byteArray){
    // 建立InputStream
    ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);

      // 默認編碼
    String utf8 = "UTF-8";
      String charset = "GB18030";

      // 開始檢測是否為UTF-8
      try {
          // 標記初始位置
        bais.mark(0);

          // 讀取前3字節
          byte[] first3Bytes = new byte[3];
          bais.read(first3Bytes);

          // 如果前三字節為 0xEFBBBF ,則為帶簽名的UTF-8
          if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) {
            return utf8;
          }

          // 前三字節判定失敗,開始檢測是否是不帶簽名的UTF-8
          // 重置讀取位置
        bais.reset();

          // 逐字節判定,直到遇到一個UTF-8編碼字符
          byte[] oneByte = new byte[1];
          boolean isUtf8 = false;
          while (-1 != bais.read(oneByte)) {
            // 如果是ASCII碼,跳過
            if (CharUtils.isAscii((char) oneByte[0])) {
                continue;
            }

              // 雙字節格式
              // 110yyyyy(C0-DF) 10xxxxxx
              if ((oneByte[0] & 0xE0) == 0xC0) {
                bais.mark(0);
                  byte[] nextOneByte = new byte[1];
                  if (bais.available() >= 1 && -1 != bais.read(nextOneByte)) {
                      if ((nextOneByte[0] & 0xC0) == 0x80) {

                          // 是GBK雙字節重疊部分?暫時當GBK處理,中文系統下,GBK默認編碼,UTF-8不常見
                          // 雙字節,第一個字節的值從0x81到0xFE,第二個字節的值從0x40到0xFE(不包括0x7F)
                          int oneByteInt = oneByte[0] & 0xff;
                          int nextOneByteInt = nextOneByte[0] & 0xff;
                          if (
                                ((0x81 & 0xff) < = oneByteInt && oneByteInt <= (0xFE & 0xff))
                                  && ((0x40 & 0xff) <= nextOneByteInt && nextOneByteInt <= (0xfe & 0xff))
                                  && (nextOneByte[0] != 0x7F)
                              ) {
                              continue;
                          }

                          // 非GBK重疊部分,歸于UTF-8
                          isUtf8 = true;
                          break;
                      }
                      bais.reset();
                  }
              }

              // 三字節格式
              // 1110xxxx(E0-EF) 10xxxxxx 10xxxxxx
              if ((oneByte[0] & 0xF0) == 0xE0) {
                  byte[] twoByte = new byte[2];
                  bais.mark(0);
                  if (bais.available() >= 2 && -1 != bais.read(twoByte)) {
                      if (((twoByte[0] & 0xC0) == 0x80) && ((twoByte[1] & 0xC0) == 0x80)) {
                          isUtf8 = true;
                          break;
                      }
                      bais.reset();
                  }
              }

              // 四字節格式
              // 11110www(F0-F7) 10xxxxxx 10xxxxxx 10xxxxxx
              if ((oneByte[0] & 0xF8) == 0xF0) {
                  byte[] threeByte = new byte[3];
                  bais.mark(0);
                  if (bais.available() >= 3 && -1 != bais.read(threeByte)) {
                      if (((threeByte[0] & 0xC0) == 0x80) && ((threeByte[1] & 0xC0) == 0x80)
                              && ((threeByte[2] & 0xC0) == 0x80)) {
                          isUtf8 = true;
                          break;
                      }
                      bais.reset();
                  }
              }

              // 五字節格式
              // 111110xx(F8-FB) 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
              if ((oneByte[0] & 0xFC) == 0xF8) {
                  byte[] fourByte = new byte[4];
                  bais.mark(0);
                  if (bais.available() >= 4 && -1 != bais.read(fourByte)) {
                      if (((fourByte[0] & 0xC0) == 0x80) && ((fourByte[1] & 0xC0) == 0x80)
                              && ((fourByte[2] & 0xC0) == 0x80)
                              && ((fourByte[3] & 0xC0) == 0x80)) {
                          isUtf8 = true;
                          break;
                      }
                      bais.reset();
                  }
              }

              // 六字節格式
              // 1111110x(FC-FD) 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
              if ((oneByte[0] & 0xFE) == 0xFC) {
                  byte[] fiveByte = new byte[5];
                  bais.mark(0);
                  if (bais.available() >= 5 && -1 != bais.read(fiveByte)) {
                      if (((fiveByte[0] & 0xC0) == 0x80) && ((fiveByte[1] & 0xC0) == 0x80)
                              && ((fiveByte[2] & 0xC0) == 0x80)
                              && ((fiveByte[3] & 0xC0) == 0x80)
                              && ((fiveByte[4] & 0xC0) == 0x80)) {
                          isUtf8 = true;
                          break;
                      }
                      bais.reset();
                  }
              }
          }

          // 依據標志位設定返回值
          if (isUtf8) {
              return utf8;
          }
      } catch (IOException e) {
      } 

      // 返回字符編碼格式
      return charset;
  }</pre> 


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!