寫着寫着,發現不容易講解,就當作記錄吧。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去解讀 文件時會報錯