1. 程式人生 > >Python編程(三)字符編碼與文件處理

Python編程(三)字符編碼與文件處理

python3 固定 one 加載 not rdl 寫到 bin 存在

計算機要想工作必須通電,也就是說‘電’驅使計算機幹活,而‘電’的特性,就是高低電平(高低平即二進制數1,低電平即二進制數0),也就是說計算機只認識數字

  編程的目的是讓計算機幹活,而編程的結果說白了只是一堆字符,也就是說我們編程最終要實現的是:一堆字符驅動計算機幹活

  所以必須經過一個過程:

  字符--------(翻譯過程)------->數字

  這個過程實際就是一個字符如何對應一個特定數字的標準,這個標準稱之為字符編碼

字符編碼 :字符--》二進制數字的標準
階段一:
ASCII:一個Bytes代表一個字符(英文+符號)
1Bytes=8bit,8bit可以表示256個字符
最初只用了後7位,127個數字,預留一位

階段二:
中國制定GBK
2Bytes代表一個字符


階段三:
語言多,混合出現亂碼
產生Unicode,統一用2Bytes代表一個字符,2**16-1 65535個

對於英文來說,這種方式多了一倍的空間,浪費空間
於是產生 UTF-8,對英文只用1Bytes,對中午用3 bYtes


unicode: 所有都是2Bytes


正確使用字符編碼:
內存中默認都是unicode
文件村:內存刷到硬盤
文件讀:硬盤讀到內存
1.文件執行前:文件存的時候用什麽編碼,讀的時候要用相同的編碼
2.文件執行時:才有了字符串這個數據類型的概念
x=‘hello‘ python3的字符串默認是unicode
unicode類型可以encode不可 x.encode(‘gbk‘)python3中

須知:

unicode:簡單粗暴,所有字符都是2Bytes,優點是字符->數字的轉換速度快,缺點是占用空間大

utf-8:精準,對不同的字符用不同的長度表示,優點是節省空間,缺點是:字符->數字的轉換速度慢,因為每次都需要計算出字符需要多長的Bytes才能夠準確表示

     所有程序,最終都要加載到內存,程序保存到硬盤不同的國家用不同的編碼格式,但是到內存中我們為了兼容萬國(計算機可以運行任何國家的程序原因在於此),統一且固定使用unicode,這就是為何內存固定用unicode的原因,你可能會說兼容萬國我可以用utf-8啊,可以,完全可以正常工作,之所以不用肯定是unicode比utf-8更高效啊(uicode固定用2個字節編碼,utf-8則需要計算),但是unicode更浪費空間,沒錯,這就是用空間換時間的一種做法,而存放到硬盤,或者網絡傳輸,都需要把unicode轉成utf-8,因為數據的傳輸,追求的是穩定,高效,數據量越小數據傳輸就越靠譜,於是都轉成utf-8格式的,而不是unicode。

技術分享

  1. 內存中使用的編碼是unicode,用空間換時間(程序都需要加載到內存才能運行,因而內存應該是盡可能的保證快)
  2. 硬盤中或者網絡傳輸用utf-8,網絡I/O延遲或磁盤I/O延遲要遠大與utf-8的轉換延遲,而且I/O應該是盡可能地節省帶寬,保證數據傳輸的穩定性。

亂碼:

亂碼一:存文件時就已經亂碼

存文件時,由於文件內有各個國家的文字,我們單以shiftjis去存,

本質上其他國家的文字由於在shiftjis中沒有找到對應關系而導致存儲失敗,用open函數的write可以測試,f=open(‘a.txt‘,‘w‘,encodig=‘shift_jis‘)

f.write(‘你\nて\n‘) #‘你‘因為在shiftjis中沒有找到對應關系而無法保存成功,只存‘て\n

‘可以成功

但當我們用文件編輯器去存的時候,編輯器會幫我們做轉換,保證中文也能用shiftjis存儲(硬存,必然亂碼),這就導致了,存文件階段就已經發生亂碼

此時當我們用shiftjis打開文件時,日文可以正常顯示,而中文則亂碼了

亂碼二:存文件時不亂碼而讀文件時亂碼

存文件時用utf-8編碼,保證兼容萬國,不會亂碼,而讀文件時選擇了錯誤的解碼方式,比如gbk,則在讀階段發生亂碼,讀階段發生亂碼是可以解決的,選對正確的解碼方式就ok了,而存文件時亂碼,則是一種數據的損壞。

總結:

無論是何種編輯器,要防止文件出現亂碼(請一定註意,存放一段代碼的文件也僅僅只是一個普通文件而已,此處指的是文件沒有執行前,我們打開文件時出現的亂碼)

核心法則就是,文件以什麽編碼保存的,就以什麽編碼方式打開

文件處理:

打開文件時,需要指定文件路徑和以何等方式打開文件,打開後,即可獲取該文件句柄,日後通過此文件句柄對該文件操作。

打開文件的模式有:

  • r ,只讀模式【默認模式,文件必須存在,不存在則拋出異常】
  • w,只寫模式【不可讀;不存在則創建;存在則清空內容】
  • x, 只寫模式【不可讀;不存在則創建,存在則報錯】
  • a, 追加模式【可讀; 不存在則創建;存在則只追加內容】

"+" 表示可以同時讀寫某個文件

  • r+, 讀寫【可讀,可寫】
  • w+,寫讀【可讀,可寫】
  • x+ ,寫讀【可讀,可寫】
  • a+, 寫讀【可讀,可寫】

"b"表示以字節的方式操作

  • rb 或 r+b
  • wb 或 w+b
  • xb 或 w+b
  • ab 或 a+b

註:以b方式打開時,讀取到的內容是字節類型,寫入時也需要提供字節類型,不能指定編碼

flush原理:

  1. 文件操作是通過軟件將文件從硬盤讀到內存
  2. 寫入文件的操作也都是存入內存緩沖區buffer(內存速度快於硬盤,如果寫入文件的數據都從內存刷到硬盤,內存與硬盤的速度延遲會被無限放大,效率變低,所以要刷到硬盤的數據我們統一往內存的一小塊空間即buffer中放,一段時間後操作系統會將buffer中數據一次性刷到硬盤)
  3. flush即,強制將寫入的數據刷到硬盤

1. open()語法

open(file[, mode[, buffering[, encoding[, errors[, newline[, closefd=True]]]]]])
open函數有很多的參數,常用的是file,mode和encoding
file文件位置,需要加引號
mode文件打開模式,見下面3
buffering的可取值有0,1,>1三個,0代表buffer關閉(只適用於二進制模式),1代表line buffer(只適用於文本模式),>1表示初始化的buffer大小;
encoding表示的是返回的數據采用何種編碼,一般采用utf8或者gbk;
errors的取值一般有strict,ignore,當取strict的時候,字符編碼出現問題的時候,會報錯,當取ignore的時候,編碼出現問題,程序會忽略而過,繼續執行下面的程序。
newline可以取的值有None, \n, \r, ”, ‘\r\n‘,用於區分換行符,但是這個參數只對文本模式有效;
closefd的取值,是與傳入的文件參數有關,默認情況下為True,傳入的file參數為文件的文件名,取值為False的時候,file只能是文件描述符,什麽是文件描述符,就是一個非負整數,在Unix內核的系統中,打開一個文件,便會返回一個文件描述符。

2. Python中file()與open()區別
兩者都能夠打開文件,對文件進行操作,也具有相似的用法和參數,但是,這兩種文件打開方式有本質的區別,file為文件類,用file()來打開文件,相當於這是在構造文件類,而用open()打開文件,是用python的內建函數來操作,建議使用open

3. 參數mode的基本取值

Character Meaning
‘r‘ open for reading (default)
‘w‘ open for writing, truncating the file first
‘a‘ open for writing, appending to the end of the file if it exists
‘b‘ binary mode
‘t‘ text mode (default)
‘+‘ open a disk file for updating (reading and writing)
‘U‘ universal newline mode (for backwards compatibility; should not be used in new code)

r、w、a為打開文件的基本模式,對應著只讀、只寫、追加模式;
b、t、+、U這四個字符,與以上的文件打開模式組合使用,二進制模式,文本模式,讀寫模式、通用換行符,根據實際情況組合使用、

常見的mode取值組合

技術分享
 1 r或rt 默認模式,文本模式讀
 2 rb   二進制文件
 3     
 4 w或wt 文本模式寫,打開前文件存儲被清空
 5 wb  二進制寫,文件存儲同樣被清空
 6     
 7 a  追加模式,只能寫在文件末尾
 8 a+ 可讀寫模式,寫只能寫在文件末尾
 9     
10 w+ 可讀寫,與a+的區別是要清空文件內容
11 r+ 可讀寫,與a+的區別是可以寫到文件任何位置 
技術分享

回到頂部

2.7 上下文管理

with open(a.txt‘,w) as f:
    pass

with open(a.txt‘,r‘) as read_f,open(b.txt‘,w) as write_f:
    data=read_f.read()
    write_f.write(data)

回到頂部

2.8 文件的修改

技術分享
import os
with open(a.txt‘,r‘,encoding=utf-8) as read_f,        open(.a.txt.swap‘,w‘,encoding=utf-8) as write_f:
    for line in read_f:
        if line.startswith(hello):
            line=哈哈哈\n
        write_f.write(line)

os.remove(a.txt)
os.rename(.a.txt.swap‘,a.txt‘)
技術分享

Python編程(三)字符編碼與文件處理