what's the python之字符編碼與文件處理


  用文本編輯器打開一個文件就是把一個文件讀入了內存中 ,所以打開文件的操作也是在內存中的,斷電即消失,所以若要保存其內容就必須點擊保存讓其存入硬盤中

python解釋器執行py文件的原理 :

    第一階段:python解釋器啟動,此時就相當於啟動了一個文本編輯器

    第二階段:python解釋器相當於文本編輯器,去打開test.py文件,從硬盤上將test.py的文件內容讀入到內存中(小復習:pyhon的解釋性,決定了解釋器只關心文件內容,不關心文件后綴名)

    第三階段:python解釋器解釋執行剛剛加載到內存中test.py的代碼( ps:在該階段,即執行時,才會識別python的語法,執行文件內代碼,執行到name="jack",會開辟內存空間存放字符串"jack")

總結:python解釋器於文件本編輯的異同

  相同點:python解釋器是解釋執行文件內容的,因而python解釋器具備讀py文件的功能,這一點與文本編輯器一樣

  不同點文本編輯器將文件內容讀入內存后,是為了顯示/編輯,而python解釋器將文件內容讀入內存后,是為了執行(執行前會識別python語法)

 

 


 

 

what's the 字符編碼?

 

字符編碼:將人輸入的字符轉換成計算機能識別的二進制數字的過程的定義的標准就叫字符編碼。

      字符=====(字符編碼)====>二進制數

  由於計算機起源於美國,所以一開始設置的字符編碼只針對英文。最早的字符編碼叫ASCII碼,后來為了滿足更多國家的文字的需求,又定制了其他的字符編碼。如中國的是GBK,日本的是shift_JIS,韓國是Euc_kr等等。

ASCII碼:一個Bytes代表一個字符(英文字符/鍵盤上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1種變化,即可以表示256個字符。(ASCII最初只用了后七位,127個數字,已經完全能夠代表鍵盤上所有的字符了(英文字符/鍵盤的所有其他字符)后來為了將拉丁文也編碼進了ASCII表,將最高位也占用了)

GBK:2Bytes代表一個字符(一個中文)

 

  因為每個國家有他們自己的標准,若同時使用多種語言時,標准不同會造成亂碼,這就需要設置一個通用的萬國標准,這就是Unicode和UTF-8

unicode:統一用2Bytes代表一個字符;優點是字符->數字的轉換速度快,缺點是占用空間大,因為英文只需1Bytes,而他統一使用2Bytes,就會造成資源浪費及占用空間大

UTF-8:對英文字符只用1Bytes表示,對中文字符用3Bytes;優點是節省空間,缺點是:字符->數字的轉換速度慢,因為每次都需要計算出字符需要多長的Bytes才能夠准確表示

注:存儲時,python2默認ASCII碼,python3默認UTF-8,可在文件開頭輸入#-*-coding:utf-8-*-,來指定解釋器用什么字符編碼

規定:

  1. 內存中使用的編碼是unicode,用空間換時間(程序都需要加載到內存才能運行,因而內存應該是盡可能的保證快)
  2. 硬盤中或者網絡傳輸用utf-8,網絡I/O延遲或磁盤I/O延遲要遠大與utf-8的轉換延遲,而且I/O應該是盡可能地節省帶寬,保證數據傳輸的穩定性。
復制代碼
注解:所有程序,最終都要加載到內存,程序保存到硬盤中不同的國家使用的是不同的編碼格式,但是到內存中我們必須兼容萬國
(計算機可以運行任何國家的程序原因在於此),所以統一且固定使用unicode。
你可能會說兼容萬國utf-8也可以,確實可以,完全可以正常工作,之所以不用是因為unicode比utf-8更高效
(uicode固定用2個字節編碼,utf-8則需要計算),但是unicode更浪費空間,沒錯,這就是用空間換時間的一種
做法。而存放到硬盤,或者網絡傳輸,都需要把unicode轉成utf-8,因為數據的傳輸,追求的是穩定,高效,數據
量越小數據傳輸就越靠譜,於是都轉成utf-8格式的,而不是unicode。
復制代碼

 

重點!:文件在內存中使用的是Unicode,若要保存到硬盤中就要經過encode存為UTF-8,硬盤中的文件是以UTF-8的形式存儲的,若要調用就必須經過decode成Unicode加載到內存中

 

注:在文件編輯器的右下角可以選擇字符編碼,一般情況下默認為UTF-8

亂碼的產生有兩種情況:

  一、一份文件包含有各國語言,若保存時用的是某個國家的標准而不是萬國標准的話,其他非本國的語言的文字就會以亂碼的形式被保存,以后再調用時一直為亂碼,等於文件被損壞,亂碼無法復原。

  二、一份文件以自己國家的標准的形式保存,在調用時用了其他的標准時,因為無法加載就會產生亂碼,此時的亂碼通過變為原來的標准就可以恢復

結論:要避免亂碼的產生,最好的方法就是以什么字符編碼保存就以什么字符編碼打開

 

瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換為UTF-8再傳輸到瀏覽器

 

如果服務端encode的編碼格式是utf-8, 客戶端內存中收到的也是utf-8編碼的二進制。

 

 


 

 

what's the 文件處理?

文件處理的流程為:

  1. 打開文件,得到文件句柄並賦值給一個變量
  2. 通過句柄對文件進行操作
  3. 關閉文件

文件打開模式:文件句柄 = open('文件路徑', '模式')

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

open:

  1 會向操作系統發起系統調用,操作會打開一個文件
  2 在python程序中會產生一個值指向操作系統打開的那個文件,我們可以把該值賦值一個變量

回收資源:f.close() 一定要做,關閉操作系統打開的文件,即回收操作系統的資源

打開文件的模式有:

  • r ,只讀模式【默認模式,文件必須存在,不存在則拋出異常】
  • w,只寫模式【不可讀;不存在則創建;存在則清空內容】
  • x, 只寫模式【不可讀;不存在則創建,存在則報錯】(基本不用)
  • a, 追加模式【可讀;   不存在則創建;存在則只追加內容】
    #r,文本文件:只讀模式,文件不存在報錯
    f=open(r'aaaa.py','r',encoding='utf-8')
    print(f.read())
    print(f.readlines())
    print(f.readable())
    print(f.writable()) #False
    f.close()
    
    #w,文本文件:只寫模式,文件不存在則創建空文件,文件存在則清空
    f=open('new.txt','w',encoding='utf-8')
    f.write('1111111\n')
    f.writelines(['22222\n','3333\n','444444\n'])
    # print(f.writable())
    f.close()
    
    #a,文本文件:只追加寫模式,文件不存在則創建,文件存在
    f=open('new_2','a',encoding='utf-8')
    print(f.readable())
    print(f.writable())
    
    f.write('33333\n')
    f.write('44444\n')
    f.writelines(['5555\n','6666\n'])
    
    f.close()

     

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

  • 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即強制將寫入的數據刷到硬盤

 

讀取的進度條,或者叫滾動條的代碼:

import time
for i in range(10):
    print('#',end='',flush=True)
    time.sleep(0.2)
else:
    print()

 

文件內光標的移動:

  一: read(3):

    1. 文件打開方式為文本模式時,代表讀取3個字符

    2. 文件打開方式為b模式時,代表讀取3個字節

  二: 其余的文件內光標移動都是以字節為單位如seek,tell,truncate

注意:

  1. seek有三種移動方式0,1,2,其中1和2必須在b模式下進行,但無論哪種模式,都是以bytes為單位移動的

  2. truncate是截斷文件,所以文件的打開方式必須可寫,但是不能用w或w+等方式打開,因為那樣直接清空文件了,所以truncate要在r+或a或a+等模式下測試效果

 

上下文管理(即創建一個新文件,在源文件中讀一行就在新文件中寫一行)

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

 

循環讀取每一行的內容:

with open('a.txt','r',encoding='utf-8') as f:
    while True:
        line=f.readline()#只適用於小文件
        if not line:break
        print(line,end='')

 

文件的修改:

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:
        write_f.write(line.replace('alex_BSB','BB_alex_SB'))

os.remove('a.txt')
os.rename('a.txt.swap','a.txt')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM