欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java判斷字節(jié)流是否是 UTF8編碼方法示例

 更新時間:2023年07月21日 10:54:41   作者:岑吾  
這篇文章主要我大家介紹了Java判斷字節(jié)流是否是 UTF8編碼方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Java 判斷字節(jié)流是否是 UTF8 編碼

遇到本來設(shè)計時使用 GBK 編碼處理的地方,在實際使用過程導(dǎo)入了 UTF8 編碼,造成了顯示文本為亂碼的現(xiàn)象,在了解 UTF8,GBK 編碼和 Unicode 標(biāo)準(zhǔn)之后,編寫了 Java 判斷字節(jié)流是否是 UTF8 編碼的程序,如果是 UTF8 編碼,則轉(zhuǎn)換成 GBK 編碼。

編碼的基礎(chǔ)知識

Unicode 是一種標(biāo)準(zhǔn),GBK 和 UTF8 是具體是編碼格式。Java 的字符都是以 Unicode 進(jìn)行存儲的,占兩或四個字節(jié)(看版本,且 Unicode 編碼中對應(yīng)關(guān)系是存在 0x00 的編碼的)。Java 中的 getBytes() 方法是和平臺(編碼)相關(guān)的,在中文系統(tǒng)中返回的可能是 GBK 或 GBK2312,在英文系統(tǒng)中返回的可能是 ISO-8859-1。

  • Unicode 標(biāo)準(zhǔn):是計算機(jī)科學(xué)領(lǐng)域里的一項業(yè)界標(biāo)準(zhǔn),包括字符集、編碼方案等,它為每種語言中的每個字符設(shè)定了統(tǒng)一并且唯一的二進(jìn)制編碼,以滿足跨語言、跨平臺進(jìn)行文本轉(zhuǎn)換、處理的要求。
  • GBK 編碼:漢字內(nèi)碼擴(kuò)展規(guī)范,國標(biāo),漢字占兩個字節(jié)。
  • UTF8 編碼:針對 Unicode 的可變長度字符編碼,用 1 到 6 個字節(jié)編碼 Unicode 字符,漢字一般占 3 個字節(jié)。

UTF8 編碼格式

如果 Unicode 字符由 2 個字節(jié)表示,則編碼成 UTF8 很可能需要 3 個字節(jié)。而如果 Unicode 字符由 4 個字節(jié)表示,則編碼成 UTF8 可能需要 6個字節(jié)。用 4 個或 6 個字節(jié)去編碼一個 Unicode 字符可能太多了,但很少會遇到那樣的 Unicode 字符。

UTF8 編碼規(guī)則:如果只有一個字節(jié)則其最高二進(jìn)制位為 0,如果是多字節(jié),其第一個字節(jié)從最高位開始,連續(xù)的二進(jìn)制位值為 1,1 的個數(shù)決定了其編碼的字節(jié)數(shù),其余各字節(jié)均以 10 開頭。

// Unicode6.1定義范圍:0~10 FFFF
// 20 0000 ~ 3FF FFFF 和 400 0000 ~ 7FFF FFFF 屬于 UCS-4,UTF8 現(xiàn)在已經(jīng)棄用了這部分內(nèi)容
---------------------------------------------------------------------------------
n | Unicode (十六進(jìn)制)    | UTF - 8 (二進(jìn)制)
--+-----------------------+------------------------------------------------------
1 | 0000 0000 - 0000 007F | 0xxxxxxx
2 | 0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx
3 | 0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
4 | 0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
---------------------------------------------------------------------------------
// 以下部分棄用
5 | 0020 0000 - 03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 | 0400 0000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
---------------------------------------------------------------------------------

Java 如何判斷單個字符編碼是否是 UTF8

假設(shè)當(dāng)前需要判定一個 byte[] 數(shù)組內(nèi)的編碼是否是 UTF8 編碼,這個 byte[] 是 String 通過 getBytes() 方法獲取的,判斷單個字符的編碼步驟如下:

  • 從 byte[] 數(shù)組中獲取一個 byte 并將它轉(zhuǎn)換成無符號類型的 int 變量 value
  • 判斷 value 是否是 ASCII 字符(小于 0x80)
  • 判斷 value 是否是無效字符(大于 0x80,小于 0xC0,參照 UTF8 編碼規(guī)則)
  • 確認(rèn)該字符編碼的是幾字節(jié) UTF8
  • 確認(rèn)該字符編碼的除第一個字節(jié)外的字節(jié)是否滿足 10xxxxxx 格式

PS:

Java getBytes() 獲取的是帶符號的十六進(jìn)制,實際處理時需要使用無符號十六進(jìn)制。

GBK 和 UTF8 中 ASCII 字符的值是一樣的。

具體程序

將十六進(jìn)制流中的所有編碼按照單個判定的方式便利一遍,如果有不符合 UTF8 編碼規(guī)則的字符出現(xiàn),則該十六進(jìn)制流就不是 UTF8 編碼格式的字串。

public static int byteToUnsignedInt(byte data) {
    return data & 0xff;
}
public boolean isUTF8(byte[] pBuffer) {
    boolean IsUTF8 = true;
    boolean IsASCII = true;
    int size = pBuffer.length;
    int i = 0;
    while (i < size) {
        int value = byteToUnsignedInt(pBuffer[i]);
        if (value < 0x80) {
            // (10000000): 值小于 0x80 的為 ASCII 字符
            if (i >= size - 1) {
                if (IsASCII) {
                    // 假設(shè)純 ASCII 字符不是 UTF 格式
                    IsUTF8 = false;
                }
                break;
            }
            i++;
        } else if (value < 0xC0) {
            // (11000000): 值介于 0x80 與 0xC0 之間的為無效 UTF-8 字符
            IsASCII = false;
            IsUTF8 = false;
            break;
        } else if (value < 0xE0) {
            // (11100000): 此范圍內(nèi)為 2 字節(jié) UTF-8 字符
            IsASCII = false;
            if (i >= size - 1) {
                break;
            }
            int value1 = byteToUnsignedInt(pBuffer[i + 1]);
            if ((value1 & (0xC0)) != 0x80) {
                IsUTF8 = false;
                break;
            }
            i += 2;
        } else if (value < 0xF0) {
            IsASCII = false;
            // (11110000): 此范圍內(nèi)為 3 字節(jié) UTF-8 字符
            if (i >= size - 2) {
                break;
            }
            int value1 = byteToUnsignedInt(pBuffer[i + 1]);
            int value2 = byteToUnsignedInt(pBuffer[i + 2]);
            if ((value1 & (0xC0)) != 0x80 || (value2 & (0xC0)) != 0x80) {
                IsUTF8 = false;
                break;
            }
            i += 3;
        }  else if (value < 0xF8) {
            IsASCII = false;
            // (11111000): 此范圍內(nèi)為 4 字節(jié) UTF-8 字符
            if (i >= size - 3) {
                break;
            }
            int value1 = byteToUnsignedInt(pBuffer[i + 1]);
            int value2 = byteToUnsignedInt(pBuffer[i + 2]);
            int value3 = byteToUnsignedInt(pBuffer[i + 3]);
            if ((value1 & (0xC0)) != 0x80
                || (value2 & (0xC0)) != 0x80
                || (value3 & (0xC0)) != 0x80) {
                IsUTF8 = false;
                break;
            }
            i += 3;
        } else {
            IsUTF8 = false;
            IsASCII = false;
            break;
        }
    }
    return IsUTF8;
}

UTF8 編碼轉(zhuǎn) GBK 編碼

// Unicode
String unicodeString = "張三";
// 獲取 UTF8 編碼
byte[] nameUTF8 = unicodeString.getBytes("utf-8");
// UTF8 編碼轉(zhuǎn) str
String str = new String(name, "utf-8");
// 獲取 GBK 編碼
byte[] nameGBK = str.getBytes("gbk");

以上就是Java判斷字節(jié)流是否是 UTF8編碼方法示例的詳細(xì)內(nèi)容,更多關(guān)于Java字節(jié)流UTF8編碼判斷的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于Feign傳輸對象無法接收參數(shù)的問題

    基于Feign傳輸對象無法接收參數(shù)的問題

    這篇文章主要介紹了基于Feign傳輸對象無法接收參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • java元注解@Inherited的使用詳解

    java元注解@Inherited的使用詳解

    這篇文章主要介紹了java元注解@Inherited的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java?Map雙列集合使代碼更高效

    Java?Map雙列集合使代碼更高效

    這篇文章主要介紹了Java?Map雙列集合使用,使你的代碼更高效,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • java 中 阻塞隊列BlockingQueue詳解及實例

    java 中 阻塞隊列BlockingQueue詳解及實例

    這篇文章主要介紹了java 中 阻塞隊列BlockingQueue詳解及實例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Maven 倉庫國內(nèi)鏡像源收藏(小結(jié))

    Maven 倉庫國內(nèi)鏡像源收藏(小結(jié))

    這篇文章主要介紹了Maven 倉庫國內(nèi)鏡像源收藏(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 詳解Java如何在CompletableFuture中實現(xiàn)日志記錄

    詳解Java如何在CompletableFuture中實現(xiàn)日志記錄

    這篇文章主要為大家詳細(xì)介紹了一種slf4j自帶的MDC類,來記錄完整的請求日志,和在CompletableFuture異步線程中如何保留鏈路id,需要的可以參考一下
    2023-04-04
  • 詳解SpringBoot Mongo 自增長ID有序規(guī)則

    詳解SpringBoot Mongo 自增長ID有序規(guī)則

    本文主要介紹springboot基于mongodb有序id生成,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 淺析Java 反射機(jī)制的用途和缺點

    淺析Java 反射機(jī)制的用途和缺點

    這篇文章給大家分析了Java 反射機(jī)制的用途和缺點以及相關(guān)知識點內(nèi)容,有興趣的朋友可以參考學(xué)習(xí)下。
    2018-07-07
  • 使用SpringBoot進(jìn)行身份驗證和授權(quán)的示例詳解

    使用SpringBoot進(jìn)行身份驗證和授權(quán)的示例詳解

    在廣闊的 Web 開發(fā)世界中,身份驗證是每個數(shù)字領(lǐng)域的守護(hù)者,在本教程中,我們將了解如何以本機(jī)方式保護(hù)、驗證和授權(quán) Spring-Boot 應(yīng)用程序的用戶,并遵循框架的良好實踐,希望對大家有所幫助
    2023-11-11
  • 分析Netty直接內(nèi)存原理及應(yīng)用

    分析Netty直接內(nèi)存原理及應(yīng)用

    Netty作為一個流行的應(yīng)用框架,它的強(qiáng)悍之處是性能強(qiáng)悍,可以輕松承載數(shù)萬并發(fā); 其編程模型簡單,容易上手; 這就給大家打開了一扇通向高性能的大門。高效io模型略去不說,我們今天主要來看看內(nèi)存控制這塊的強(qiáng)大之處
    2021-06-06

最新評論