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

java中的編碼轉(zhuǎn)換過程(以utf8和gbk為例)

 更新時間:2023年04月13日 10:14:46   作者:請叫我徐先生  
這篇文章主要介紹了java中的編碼轉(zhuǎn)換過程(以utf8和gbk為例),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

java中的編碼轉(zhuǎn)換(以utf8和gbk為例)

在正常javaweb開發(fā)中經(jīng)常會發(fā)現(xiàn)字符轉(zhuǎn)換的需求,會存在中文字符轉(zhuǎn)換亂碼的現(xiàn)象,如何解決以及其轉(zhuǎn)換原理我至今懵懵懂懂,于是專門寫了個測試代碼進(jìn)行嘗試,總算理清了編碼,先上結(jié)論,總結(jié)如下:

utf8中存放有各種語言編碼,當(dāng)前主流開發(fā)中會使用utf8進(jìn)行編碼解碼,該方式不會產(chǎn)生亂碼,產(chǎn)生亂碼有以下幾種情況

  • 1、gbk(中文)、iso-8859-1(無中文)等其他方式進(jìn)行編碼,則只能用其對應(yīng)方式進(jìn)行解碼,否則為亂碼
  • 2、使用utf8進(jìn)行編碼用其他方式解碼則會導(dǎo)致亂碼,需進(jìn)行一次轉(zhuǎn)換
  • 3、使用無對應(yīng)字符(中文)的字符集(iso-8859-1)編碼會導(dǎo)致亂碼,且無法還原解碼

以下是針對以上情況的代碼測試

1.如何編碼就如何解碼

/**
?* 測試編碼轉(zhuǎn)換 中文 => utf-8 編碼 - 解碼
?*/
@Test
public void test0() {
? ? String test = "測試";
? ? System.out.println(Arrays.toString(test.getBytes(StandardCharsets.UTF_8)));//[-26, -75, -117, -24, -81, -107]
? ? System.out.println(new String(test.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));//測試
}
/**
?* 測試編碼轉(zhuǎn)換 中文 => gbk 編碼 - 解碼
?*/
@Test
public void test1() throws UnsupportedEncodingException {
? ? String test = "測試";
? ? System.out.println(Arrays.toString(test.getBytes("gbk")));//[-78, -30, -54, -44]
? ? System.out.println(new String(test.getBytes("gbk"), "GBK"));//測試
}

utf8編碼 - 錯誤形式解碼

/**
?* 測試編碼轉(zhuǎn)換 中文 => utf-8 編碼- gbk解碼
?*/
@Test
public void test2() throws UnsupportedEncodingException {
? ? String test = "測試";
? ? System.out.println(Arrays.toString(test.getBytes(StandardCharsets.UTF_8)));//[-26, -75, -117, -24, -81, -107]
? ? System.out.println(new String(test.getBytes(StandardCharsets.UTF_8), "gbk"));//嫻嬭瘯
}

正確做法,按錯誤的解碼形式(gbk)作為中轉(zhuǎn),將其按錯誤形式(gbk)重新還原編碼(utf8-encode),再使用utf8進(jìn)行一次正確解碼(utf8-decode)即可得到原來的字符

/**
?* 測試編碼轉(zhuǎn)換 中文 => utf-8 編碼 - gbk 解碼 ===> gbk 編碼 - utf-8解碼
?* "測試" => (utf8-encode)[-26, -75, -117, -24, -81, -107] => (gbk-decode)嫻嬭瘯
?* "嫻嬭瘯" => (utf8-encode)[-26, -75, -117, -24, -81, -107] => (utf8-decode)"測試"
?*/
@Test
public void test3() throws UnsupportedEncodingException {
? ? String test = "測試";
? ? String test_gbk_utf8 = new String(test.getBytes(StandardCharsets.UTF_8), "gbk");
? ? System.out.println(test_gbk_utf8);//嫻嬭瘯
? ? String test_utf8_gbk = new String(test_gbk_utf8.getBytes("gbk"), StandardCharsets.UTF_8);
? ? System.out.println(test_utf8_gbk);//測試

}

3.無對應(yīng)字符編碼

@Test
? ? public void test4() throws UnsupportedEncodingException {
? ? ? ? String test = "測試";
? ? ? ? System.out.println(Arrays.toString(test.getBytes(StandardCharsets.ISO_8859_1)));//[63, 63]
? ? ? ? System.out.println(new String(test.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.ISO_8859_1));//??
? ? }

該情況下即使使用原先的編碼方式進(jìn)行解碼也無法還原字符了,屬于不可逆的狀態(tài)

java編碼格式的轉(zhuǎn)換以及亂碼恢復(fù)

如何在java中進(jìn)行編碼格式轉(zhuǎn)換

下面這行代碼的含義是: 獲取目標(biāo)字符串str的gbk編碼格式的二進(jìn)制碼,然后將二進(jìn)制碼按照utf8編碼格式重新編碼成字符串,當(dāng)然,下面這種寫法百分百會亂碼,因為編碼格式不一致.

new String(str.getBytes("gbk"),"utf8")

首先什么情況會亂碼

如果要傳輸一個字符串,首先要按照一定的編碼格式將字符串轉(zhuǎn)換成字節(jié)流,當(dāng)字節(jié)流傳輸?shù)浇邮辗降臅r候再將字節(jié)流按照某種編碼格式轉(zhuǎn)換成字符串.亂碼也正是產(chǎn)生在重新轉(zhuǎn)換成字符串的過程中.以下是我對中文亂碼的測試:

? String str="彩虹";
? ? ? ? String [] a=new String[] {"gbk","unicode","utf8","gb2312"};
? ? ? ? for (int i=0;i<a.length;i++){
? ? ? ? ? ? for (int j=0;j<a.length;j++){
? ? ? ? ? ? ? ? System.out.println("二進(jìn)制格式: ? "+a[i]+"編碼格式: ?"+a[j]);
? ? ? ? ? ? ? ? System.out.println("編碼后的字符串: ?"+new String(str.getBytes(a[i]),a[j]));
?
? ? ? ? ? ? }
? ? ? ? }

二進(jìn)制格式:   gbk編碼格式:  gbk
編碼后的字符串:  彩虹
二進(jìn)制格式:   gbk編碼格式:  unicode
編碼后的字符串:  ??
二進(jìn)制格式:   gbk編碼格式:  utf8
編碼后的字符串:  ???
二進(jìn)制格式:   gbk編碼格式:  gb2312
編碼后的字符串:  彩虹
二進(jìn)制格式:   unicode編碼格式:  gbk
編碼后的字符串:  ?_i唝
二進(jìn)制格式:   unicode編碼格式:  unicode
編碼后的字符串:  彩虹
二進(jìn)制格式:   unicode編碼格式:  utf8
編碼后的字符串:  ??_i?y
二進(jìn)制格式:   unicode編碼格式:  gb2312
編碼后的字符串:  ??_i?y
二進(jìn)制格式:   utf8編碼格式:  gbk
編碼后的字符串:  褰╄櫣
二進(jìn)制格式:   utf8編碼格式:  unicode
編碼后的字符串:  ?馹
二進(jìn)制格式:   utf8編碼格式:  utf8
編碼后的字符串:  彩虹
二進(jìn)制格式:   utf8編碼格式:  gb2312
編碼后的字符串:  褰╄??
二進(jìn)制格式:   gb2312編碼格式:  gbk
編碼后的字符串:  彩虹
二進(jìn)制格式:   gb2312編碼格式:  unicode
編碼后的字符串:  ??
二進(jìn)制格式:   gb2312編碼格式:  utf8
編碼后的字符串:  ???
二進(jìn)制格式:   gb2312編碼格式:  gb2312
編碼后的字符串:  彩虹

可以看出,如果二進(jìn)制編碼格式和字符串的編碼格式不同就會引起亂碼.

為什么gbk,gb2312轉(zhuǎn)換沒有亂碼?

gbk和gb2312之間的轉(zhuǎn)換沒有亂碼是因為gbk是gb2312的增強版本,支持更多的漢字編碼,所以如果二進(jìn)制編碼格式是gbk而解碼格式是gb2312,這種情況是有可能出現(xiàn)部分漢字亂碼的.

亂碼的數(shù)據(jù)可以轉(zhuǎn)變回來嗎?

上述結(jié)果中的亂碼其實可以大致分為兩種,一種是復(fù)雜的漢字和圖形組合,一種是"?".

如果希望恢復(fù)的亂碼數(shù)據(jù)中有問號,那么這條數(shù)據(jù)恢復(fù)的可能性就不大了.因為除了"?"的其他亂碼其實都是有自己的編碼規(guī)則的,只要逆向的解碼并按照正確的編碼格式重新編碼就可以恢復(fù).但是"?"除外,因為當(dāng)字節(jié)流按照某種編碼格式重新編譯的時候,字節(jié)數(shù)據(jù)中無法按照該編碼格式轉(zhuǎn)換成有意義字符的字節(jié)都會轉(zhuǎn)換成"?",所以就算逆向的編碼成字節(jié)流,所有的"?"都會轉(zhuǎn)換成同一字節(jié),也就失去了他本身的意義.

如果亂碼中不包含"?",那么還是有希望轉(zhuǎn)換回去的,我以上述亂碼中的 "褰╄櫣" 為例重新進(jìn)行了一次轉(zhuǎn)換,代碼如下:

? ? ? ?String str="褰╄櫣";
? ? ? ? String [] charset=new String[] {"gbk","unicode","utf8","gb2312"};
? ? ? ? for (int i=0;i<charset.length;i++){
? ? ? ? ? ? for (int j=0;j<charset.length;j++){
? ? ? ? ? ? ? ? System.out.println("二進(jìn)制格式: ? "+charset[i]+"編碼格式: ?"+charset[j]);
? ? ? ? ? ? ? ? System.out.println("編碼后的字符串: ?"+new String(str.getBytes(charset[i]),charset[j]));
?
? ? ? ? ? ? }
? ? ? ? }

二進(jìn)制格式:   gbk編碼格式:  gbk
編碼后的字符串:  褰╄櫣
二進(jìn)制格式:   gbk編碼格式:  unicode
編碼后的字符串:  ?馹
二進(jìn)制格式:   gbk編碼格式:  utf8
編碼后的字符串:  彩虹
二進(jìn)制格式:   gbk編碼格式:  gb2312
編碼后的字符串:  褰╄??
二進(jìn)制格式:   unicode編碼格式:  gbk
編碼后的字符串:  ??0%Dj?
二進(jìn)制格式:   unicode編碼格式:  unicode
編碼后的字符串:  褰╄櫣
二進(jìn)制格式:   unicode編碼格式:  utf8
編碼后的字符串:  ???0%Dj?
二進(jìn)制格式:   unicode編碼格式:  gb2312
編碼后的字符串:  ???0%Dj?
二進(jìn)制格式:   utf8編碼格式:  gbk
編碼后的字符串:  瑜扳晞婭?
二進(jìn)制格式:   utf8編碼格式:  unicode
編碼后的字符串:  ??閄?
二進(jìn)制格式:   utf8編碼格式:  utf8
編碼后的字符串:  褰╄櫣
二進(jìn)制格式:   utf8編碼格式:  gb2312
編碼后的字符串:  瑜扳??婭?
二進(jìn)制格式:   gb2312編碼格式:  gbk
編碼后的字符串:  褰╄?
二進(jìn)制格式:   gb2312編碼格式:  unicode
編碼后的字符串:  ??
二進(jìn)制格式:   gb2312編碼格式:  utf8
編碼后的字符串:  彩??
二進(jìn)制格式:   gb2312編碼格式:  gb2312
編碼后的字符串:  褰╄?

可以看到 其中一種轉(zhuǎn)換方式成功的將亂碼轉(zhuǎn)變回了正常的中文漢字

二進(jìn)制格式:   gbk編碼格式:  utf8
編碼后的字符串:  彩虹

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java集合系列之LinkedList源碼分析

    Java集合系列之LinkedList源碼分析

    這篇文章主要為大家詳細(xì)介紹了Java集合系列之LinkedList源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • quartz的簡單使用、SpringBoot使用和自定義數(shù)據(jù)源集成方式

    quartz的簡單使用、SpringBoot使用和自定義數(shù)據(jù)源集成方式

    這篇文章主要介紹了quartz的簡單使用、SpringBoot使用和自定義數(shù)據(jù)源集成方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教<BR>
    2024-01-01
  • Spring Boot利用JSR303實現(xiàn)參數(shù)驗證的方法實例

    Spring Boot利用JSR303實現(xiàn)參數(shù)驗證的方法實例

    這篇文章主要給大家介紹了關(guān)于Spring Boot利用JSR303實現(xiàn)參數(shù)驗證的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • ReentrantLock源碼詳解--公平鎖、非公平鎖

    ReentrantLock源碼詳解--公平鎖、非公平鎖

    ReentrantLock重入鎖,是實現(xiàn)Lock接口的一個類,也是在實際編程中使用頻率很高的一個鎖,表示能夠?qū)蚕碣Y源能夠重復(fù)加鎖,即當(dāng)前線程獲取該鎖再次獲取不會被阻塞。下面我們來深入了解一下它吧
    2019-06-06
  • Java集合中的Collection接口總結(jié)

    Java集合中的Collection接口總結(jié)

    這篇文章主要介紹了Java集合中的Collection接口總結(jié),Collection 接口是 List和Set接口的父接口,該接口里定義的方法既可用于操作 Set 集合,也可用于操作 List 集合,需要的朋友可以參考下
    2023-11-11
  • Java數(shù)據(jù)結(jié)構(gòu)之二叉排序樹的實現(xiàn)

    Java數(shù)據(jù)結(jié)構(gòu)之二叉排序樹的實現(xiàn)

    二叉排序樹(Binary Sort Tree),又稱二叉查找樹(Binary Search Tree),亦稱二叉搜索樹。本文詳細(xì)介紹了二叉排序樹的原理,并且提供了Java代碼的完全實現(xiàn)。需要的可以參考一下
    2022-01-01
  • Java深入分析了解平衡二叉樹

    Java深入分析了解平衡二叉樹

    平衡二叉樹又被稱為AVL樹(有別于AVL算法),且具有以下性質(zhì):它是一棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,并且左右兩個子樹都是一棵平衡二叉樹。本文將詳解介紹一下平衡二叉樹的原理與實現(xiàn),需要的可以參考一下
    2022-06-06
  • java高級用法之JNA中的Function

    java高級用法之JNA中的Function

    這篇文章主要介紹了java高級用法之JNA中的Function,JAVA中的映射在JNA中就是一個function。通過或者function對象,我們可以實現(xiàn)一些非常強大的功能,下面一起進(jìn)入文章看看具體內(nèi)容吧
    2022-04-04
  • springboot?jpa之返回表中部分字段的處理詳解

    springboot?jpa之返回表中部分字段的處理詳解

    這篇文章主要介紹了springboot?jpa之返回表中部分字段的處理詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java多線程Atomic包操作原子變量與原子類詳解

    Java多線程Atomic包操作原子變量與原子類詳解

    這篇文章主要介紹了Java多線程Atomic包操作原子變量與原子類詳解,簡單介紹了Atomic,同時涉及java.util.concurrent中的原子變量,Atomic類的作用等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11

最新評論