亂碼,編碼

寫着寫着,發現不容易講解,就當作記錄吧。php

 

編碼是什麼? 爲何我看到的是亂碼?python

下面我來說講我理解的編碼:sql

我要把這段筆記:「我要把這段筆記保存電腦中,等之後用到的時候能夠再看」使用vim編輯器保存電腦中,等之後用到的時候能夠再看。爲何之後能再看了?shell

呵呵,這裏你們都會說固然能看到啊,對。  可是爲何有些時候顯示是亂碼了?數據庫

 

首先,咱們上電腦上文件的都是以01的方式放在電腦中,那爲何cat a時會打印出咱們想要的內容了?vim

這時咱們要知道爲何要acsii碼,utf-8編碼,gbk編碼,unicode編碼等?centos

關於爲何要這些編碼,我這裏不作講解,請閱讀bash

經過閱讀上面連接的文章,咱們知道了中文的utf8編碼是3字節,中文的gbk編碼是2字節,英文的acsii/utf8/gbk編碼都是1字節。服務器

我先說明下:網絡

「個人」utf-8編碼爲:\xe6\x88\x91 ,gbk編碼爲:\xce\xd2。

咱們用crt 打開一個遠程終端,用vim編輯的文字,或在命令行輸入的文字,是以什麼樣的方式發送到服務器的了?

固然是抓包咯,我在shell輸入「我」:

抓包到的是:

能夠看到,這裏是utf-8編碼後發送到服務器端的,這是爲何了?爲何不是gbk編碼後發送過去了?

這是咱們在crt上配置的,crt以對收到的網絡數據或系統輸入數據都有 utf8來編碼和解碼。這配置gbk那就以gbk來編碼解碼。

這裏咱們在文件b中輸入「我」顯示4個字節,「咱們在」,ll顯示10個字節,這就說明存儲的中文是utf8編碼存儲的。

爲何是utf8存儲了?  我以爲就是由於咱們發送過去的就是utf8編碼的咯(crt配置的utf8)。

那爲何cat b時,會正確的顯示正文了?

我認爲cat b時不會管你是什麼編碼,直接用二進制的方式讀取,而後發送到crt顯示,固然就能正確顯示。

全部我認爲,要讓咱們編輯的文件不是亂碼,那就是crt設置utf8寫的文件,cat時crt也要設置爲utf8,crt設置爲gbk時寫的文件,cat時crt也要是gbk。這裏貌似跟系統環境變量(echo $LANG)沒啥關係?

環境變量在df -h呀,ll時是有用的。

LANG=zh_CN.GB18030 ,LANG=zh_CN.UTF-8,LANG=en_US.UTF-8,LANG=en_US.GB18030,

點"."前面的應該是在dh -h第一行,或系統報錯時的錯誤提示有用,zh_CN的話就顯示中文,en_US的話顯示英文,有待考證

 1 [centos@liujin-1 ~]$ echo $LANG
 2 en_US.UTF-8
 3 [centos@liujin-1 ~]$ df -h     
 4 Filesystem      Size  Used Avail Use% Mounted on
 5 /dev/vda2        50G   37G   11G  79% /
 6 tmpfs           3.9G   12K  3.9G   1% /dev/shm
 7 /dev/vda1       190M   44M  136M  25% /boot
 8 /dev/vda4        12G  685M   11G   7% /data01
 9 cm_processes    3.9G   20M  3.9G   1% /var/run/cloudera-scm-agent/process
10 [centos@liujin-1 ~]$ hahah
11 -bash: hahah: command not found
12 [centos@liujin-1 ~]$ ls aaasfa
13 ls: cannot access aaasfa: No such file or directory
14 [centos@liujin-1 ~]$ 

 

 咱們不能說.後面的UTF-8時不支持中文,這是錯的,UTF-8固然支持中文,UTF-8和GBK都是存儲字符的一種方式。

 

咱們還常常用到的oracle,oracle怎麼設置環境變量了?

 NLS_LANG=AMERICAN_AMERICA.AL32UTF8, NLS_LANG=AMERICAN_AMERICA.ZHS16GBK ,d點「.」前面應該是sql中出現錯誤時應該提示中文錯誤仍是英文錯誤,點後面的是告訴數據庫客戶端發過來的字符集時utf8仍是gbk的,或者是數據庫要發給客戶端的話,要發送utf8格式的仍是gbk格式的。

好比我數據庫裏的數據是utf8存放的,NLS_LANG設置的是gbk,那客戶端找數據庫查詢數據時,會把存儲的utf8的編碼轉換爲gbk再傳給客戶端,好比數據庫存儲「我」存儲在數據庫的磁盤上是「\xe6\x88\x91」,那發給客戶端時會把「我」的編碼轉爲「\xce\xd2」。,而後再發送給客戶端。

 

一、若是個人sql文件是utf8保存的insert.sql,我想在服務器上sql>@insert.sql時設置環境變量export NLS_LANG=AMERICAN_AMERICA.AL32UTF8,sql打開這個insert.sql文件仍是二進制的方式打開,而後NLS_LANG變量就會告訴sql傳輸的編碼是utf8。若是是gbk保存,設置export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK,跟數據庫存儲的編碼不要緊(select userenv('language') from dual;)

二、若是我想select * from tables;時,crt編碼和NSL_LANG編碼保持一致。數據庫讀取數據後,會把數據轉換爲NLS_LANG的編碼,全部crt就會收到NLS_LANG的編碼,因此crt得編碼就要跟NLS_LANG同樣。

 

有一種狀況,crt設置的gbk,NLS_LANG設置的utf8,數據庫存儲設置的utf8,這是我要插入一個"我」到數據庫,

crt是bgk,全部發送到sql的是\xce\xd2,數據庫收到的就是\xce\xd2。

NLS_LANG和數據庫存儲用的都是utf8,因此數據庫不會進行轉碼操做,直接把\xce\xd2存儲在數據庫的磁盤上。

當你讀這個「我」的時候,NLS_LANG和數據庫存儲字符集都是utf8,數據庫就會直接把\xce\xd2發送給客戶端,客戶端收到後,再crt上顯示,crt有事gbk的編碼,因此就顯示了「我」字。

可是,上面說了crt的字符集要跟NLS_LANG同樣啊,對的,那上面那種狀況怎麼能正確的顯示「我」了?  由於了插入的時候,crt字符集就設置錯了!!!

建議:

在手動insert插入或select讀取時,crt,NLS_LANG,和數據庫存儲字符集設置的同樣,可是crt和NLS_LANG儘可能保持一致!!!

@insert.sql插入數據時,NLS_LANG和insert.sql的字符集要一致。

 

 oracle編碼能夠看視頻:字符集概述字符集正確設置及相關操做 

 

 咱們的python2和python3了?

執行python2 a.py,python2怎麼知道a.py的編碼方式了?

 

我認爲python默認會議ascii的方式打開a.py文件,而個人a文件是以utf8的編碼存儲的,而且裏面有中文,全部上圖報錯,還說沒有指定編碼方式。

 全部咱們在寫python2的時候會在文件開頭寫上#! -*- coding:utf8 -*-

 ,這樣python解釋器就會以utf8的方式對讀取的文件進行解碼。

 

能夠看到python2中,「我」是字符串類型,以utf-8或gbk的方式保存在內存中,(utf8仍是gbk經過coding:utf8/coding:gbk,或系統環境變量LANG的方式肯定),python內存中的編碼跟蹤環境變量走。

 

python3默認以utf8的格式解讀a.py(用utf8編碼存儲的)

python3中,"我」是str類型,unicode編碼放在內存中的,能夠進行編碼操做。

 若是文件是gbk編碼,那python3解釋器默認用utf8去解讀 文件時會報錯

 

相關文章
相關標籤/搜索