你瞭解java中的幾種編碼方式?解決亂碼問題可能並不麻煩

前言

編碼的轉換一般在IO機制中使用,一個好的編碼能夠爲咱們節省不少空間,在某種程度上提升咱們應用的效率。因爲以前就知道String中的轉換方式,還有一些工具類,所以今天就好好的整理一下java中jdk提供的幾種轉換方式,但願對你有幫助。java

1、編碼轉換原理

一、爲何須要編碼

咱們知道計算機存儲信息的最小單位是一個字節8位,可以表示256個字符。這對於早起的英文來講足夠了。即便是加上一些常見符號也足夠。因而在1965年美國製定了ASCII編碼,主要用於英語和西歐語言,一開始128個,後來加到了256。工具

後來隨着時間的發展,中國、日本等國的計算機也開始蓬勃發展,因而計算機不只僅要存儲英文了,也開始存儲中文。可是中文咱們都知道幾萬個太多了,一個字節確定放不下。怎麼辦呢?一個字節表示不下,那就多用幾個字節就行了。這樣不只能夠表示漢字,還能夠避免了與ASCII編碼的衝突。這幾個字節在存儲的時候再轉化爲bit,完美!劃重點哈,編碼解決的就是字節和字符之間的轉化問題。編碼

二、編碼方式

既然是編碼,那些大佬早就考慮到了這些問題,並提拱了多種編碼方式,常見的有 ASCII、ISO-8859-一、GB23十二、GBK、UTF-八、UTF-16 等。它們規定了轉化的規則,按照這個規則就可讓計算機正確的表示咱們的字符。spa

像GB23十二、GBK、UTF-八、UTF-16等不少種方式均可以表示漢字,他們有什麼區別呢?code

(1)GB2312

它是雙字節編碼,總的編碼範圍是 A1-F7,其中從 A1-A9 是符號區,總共包含 682 個符號,從 B0-F7 是漢字區,包含 6763 個漢字。這個是中國1981年搞出來的。這種編碼是一個漢字兩個字節。blog

(2)GBK

它的編碼範圍是 8140~FEFE(去掉 XX7F)總共有 23940 個碼位,它能表示 21003 個漢字。這個是中國在1995年搞出來的,主要是用於GB2312編碼的補充。這種編碼依然是一個漢字兩個字節。ip

(3)Unicode

上面看到,中國能夠作出了一個編碼,日本也能夠作出來一個編碼,時間久了每一個國家都有着本身的一套編碼,就不可避免的形成衝突。因而Unicode出來了,把全部語言統一塊兒來合成一個規則。這種編碼是定長的字節數。utf-8

(4)UTF8

既然Unicode是定長的字節數,那麼存儲一個複雜的漢字可能須要三個字節,可是爲了保證是2的冪數集,就會自動擴充爲4個字節,別看着一個字節之差,存儲的字數多了就會極大的浪費空間。是因而而 UTF-8 採用了一種變長技術,每一個編碼區域有不一樣的字碼長度。不一樣類型的字符能夠是由 1~6 個字節組成。rem

以上這些編碼方式會爲每個漢字或者是字母創建一個編碼庫,在編碼的時候字母和編碼一一對應。字符串

三、爲何會出現亂碼?

這個問題就是由於編碼和解碼是採用了不一樣的或者是不兼容的編碼方案。好比一個用UTF-8編碼的後的字符。再用GBK去解碼,因爲兩個字符集的編碼庫不同。同一個漢字在兩個編碼庫的位置也不同。因而就出現了亂碼。

四、java如何解決亂碼問題?

這個問題其實就是java中如何使用編碼規則,由於使用好了編碼規則。才能夠很好地解決亂碼問題。

(1)IO流

編碼的目的上面已經說了,主要是字節和字符之間的轉化。既然涉及到字節和字符很容易咱們就能想到java中的IO流。也就是說java中編碼的轉換其實就是IO流中的類來實現的。

最核心的就是上面幾個類,固然這裏只是給出了輸入的一部分,還有一些輸出的類。

(2)String

String類中也提供了一些轉碼的方法。下面咱們會經過實例來講明。爲何String能夠實現呢?這是由於String底層保存的其實就是一個一個字節,並且String還有方法直接轉化爲字符。因此String確定也能實現。

(3)Charset

這個Charset是javaNIO中的一個類,整個流程就是讀取數據,而後轉化爲byte,也就是字符。而後從新編碼成字符就OK了。

下面咱們使用代碼來實現一下:

2、代碼實現

一、IO流

首先是IO流實現,這種經過輸入輸出流能夠直接的指定編碼規則。

`public void convertionFile() throws IOException {
  File file = new File("./愚公要移山.txt");
  FileInputStream fis = new FileInputStream(file);
  InputStreamReader inReader = new InputStreamReader(fis, "gbk");
  FileOutputStream fos = new FileOutputStream(file);
  OutputStreamWriter outReader = new OutputStreamWriter(fos, "utf-8");
        //這種輸入gbk,輸出utf-8確定會出現錯誤
 }`

二、String

使用string是最方便的,代碼也比較簡潔,適用於字符串的編碼。

`public void convertionString() throws UnsupportedEncodingException {
  String s = "愚公要移山,碼農飛上天";
  // 正常狀況下轉碼的過程
  byte[] b = s.getBytes("gbk");// 編碼
  String sa = new String(b, "gbk");// 解碼
  System.out.println(sa);
  // 錯誤狀態下轉碼的過程
  b = sa.getBytes("utf-8");// 編碼使用utf-8
  sa = new String(b, "gbk");// 解碼使用gbk
  System.err.println(sa);
}
//控制檯輸出:
//愚公要移山,碼農飛上天
//鎰氬叕瑕佺Щ灞憋紝鐮佸啘椋炰笂澶?
`

三、Charset

`public void convertionCharset() throws IOException {
  Charset charset = StandardCharsets.UTF_8;
  // 從字符集中建立相應的編碼和解碼器
  CharsetEncoder encoder = charset.newEncoder();
  CharsetDecoder decoder = charset.newDecoder();
  // 構造一個buffer
  CharBuffer charBuffer = CharBuffer.allocate(64);
  charBuffer.put('A');
  charBuffer.flip();
  // 將字符序列轉換成字節序列
  ByteBuffer bb = encoder.encode(charBuffer);
  // 將字節序列轉換成字符序列
  bb.flip();
  CharBuffer cb = decoder.decode(bb);
}
`

以上就是三種基本的實現方式,固然還有一些其餘的,好比Spring中提供的編碼轉換工具等等。在這裏就不說了,由於技術太多,實現的方式也太多,咱們就看這幾種便可。

相關文章
相關標籤/搜索