程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python升級之路( Lv9 ) 文件操作

編輯:Python

Python系列文章目錄

第一章 Python 入門
第二章 Python基本概念
第三章 序列
第四章 控制語句
第五章 函數
第六章 面向對象基礎
第七章 面向對象深入
第八章 異常機制
第九章 文件操作


文件操作

  • Python系列文章目錄
  • 前言
  • 一、什麼是文件操作
    • 1. 文件分類
    • 2. 常用編碼
      • ASCII
      • GBK
      • Unicode
      • UTF-8
  • 二、文件操作
    • 1. 創建文件對象
    • 2. 文件的寫入
      • 基本文件的寫入操作
      • 中文亂碼
        • 代碼編寫時
        • 控制台輸出時
      • write()/writelines()寫入數據
      • close()關閉文件流
      • with語句(上下文管理器)
    • 3. 文件的讀取
      • 二進制文件的讀取和寫入
    • 4. 文件對象的常用屬性和方法
      • 文件任意位置操作
  • 三、文件操作拓展模塊
    • 1. pickle序列化模塊
    • 2. csv文件的操作
      • csv文件讀取
      • csv文件寫入
    • 3. os和os.path模塊
      • os模塊-調用操作系統命令
      • os模塊-文件和目錄操作
      • os.path模塊
      • walk()遞歸遍歷所有文件和目錄
      • 遞歸遍歷目錄下所有文件
    • 4. shutil模塊(拷貝和壓縮)

前言

在本章節, 主要介紹了文件操作相關的API方法使用
首先我們將會學習什麼是文件操作, 以及文件分類還有在IO操作時會用到的常用編碼介紹
然後我們學習了文件操作的流程, 創建->寫入->關閉
在然後我們學習了文件的拓展, 序列化模塊pickle, 文件操作模塊csv, 系統操作調用模塊os和os.path以及文件拷貝壓縮模塊shutil


一、什麼是文件操作

一個完整的程序一般都包括數據的存儲和讀取;我們在前面寫的程序數據都沒有進行實際的存儲,因此python解釋器執行完數據就消失了
實際開發中,我們經常需要從外部存儲介質(硬盤、光盤、U盤等)讀取數據,或者將程序產生的數據存儲到文件中,實現“持久化”保存

1. 文件分類

按文件中數據組織形式,我們把文件分為文本文件和二進制文件兩大類:

  1. 文本文件
    文本文件存儲的是普通“字符”文本,python默認為 unicode 字符集,可以使用記事本程序打開

  2. 二進制文件
    二進制文件把數據內容用“字節”進行存儲,無法用記事本打開, 必須使用專用的軟件解碼.
    常見的有:MP4視頻文件、MP3音頻文件、JPG圖片、doc文檔等等

2. 常用編碼

在操作文本文件時,經常會操作中文,這時候就經常會碰到亂碼問題.
為了解決中文亂碼問題,需要學習下各個編碼之前的問題.

常用編碼之間的關系如下:

ASCII

全稱為 American Standard Code for Information Interchange ,美國信息交換標准代碼,
這是世界上最早最通用的單字節編碼系統,主要用來顯示現代英語及其他西歐語言

注意事項:

  • ASCII 碼用7位表示,只能表示128個字符. 只定義了2^7=128個字符,用7bit即可完全編碼,
    而一字節8bit的容量是256,所以一字節 ASCII 的編碼最高位總是0
  • ASCll 碼對應碼表如下: ASCll 碼表

GBK

GBK即漢字內碼擴展規范,英文全稱Chinese Internal Code Specification.
GBK編碼標准兼容GB2312,共收錄漢字21003個、符號883個,並提供1894個造字碼位,簡、繁體字融於一庫。
GBK采用雙字節表示,總體編碼范圍為8140-FEFE,首字節在81-FE 之間,尾字節在40-FE 之間

Unicode

Unicode 編碼設計成了固定兩個字節,所有的字符都用16位2^16=65536表示,包括之前只占8位的英文字符等,所以會造成空間的浪費
Unicode 完全重新設計,不兼容 iso8859-1 ,也不兼容任何其他編碼

UTF-8

對於英文字母, unicode 也需要兩個字節來表示, 所以 unicode 不便於傳輸和存儲.
因此而產生了 UTF編碼 , UTF-8 全稱是( 8-bit UnicodeTransformation Format )

注意事項

  • UTF 編碼兼容 iso8859-1 編碼,同時也可以用來表示所有語言的字符
  • UTF 編碼是不定長編碼,每一個字符的長度從1-4個字節不等.
    英文字母都是用一個字節表示,而漢字使用三個字節
  • 一般項目都會使用 UTF-8
    我們之所以傾向於使用UTF-8 , 是因為其不定長編碼可以在節省內存的同時能夠完全兼容中文

二、文件操作

1. 創建文件對象

open() 函數用於創建文件對象,基本語法格式如下:open(文件名[,打開方式])

注意:

  • 如果只是文件名,代表在當前目錄下的文件. 文件名可以錄入全路徑,比如: D:\a\b.txt
    可以使用原始字符串 r“d:\b.txt” 減少 \ 的輸入, 因此以上代碼可改寫成 f = open(r"d:\b.txt","w")

  • 作為入參的打開方式如下(經常會用!!!)

  • 文本文件對象和二進制文件對象的創建
    如果是二進制模式 b ,則創建的是二進制文件對象,處理的基本單元是“字節”
    如果沒有增加模式 b ,則默認創建的是文本文件對象,處理的基本單元是“字符”

2. 文件的寫入

文本文件的寫入一般就是三個步驟:

  • 創建文件對象
  • 寫入數據
  • 關閉文件對象

基本文件的寫入操作

實操代碼

# 1.使用open()方式
f = open(r"d:\a.txt", "a")
s = "TimePause\n時間靜止\n"
f.write(s)
f.close()

結果展示

中文亂碼

代碼編寫時

windows 操作系統默認的編碼是 GBK , Linux 操作系統默認的編碼是 UTF- 8 .
當我們用 open() 時,調用的是操作系統相關api來打開的文件,並且默認的編碼是 GBK
但是由於我們通常習慣將所有代碼編碼都設置成 UTF- 8 ., 因此在打開時會出現亂碼問題, 如下圖所示


解決方案:
按照上圖提示, 將文本編碼設置成 GBK格式讀取即可

注意:
我們還可以通過指定編碼來解決中文亂碼問題. 因為我們將pycharm文本讀寫編碼都設置成 utf-8,
因此只要我們在文件寫入的時候規定編碼為 utf-8(默認gbk), 那麼我們在讀取時就不會出現亂碼. 如下代碼

實操代碼

# 【示例】通過指定文件編碼解決中文亂碼問題
f = open(r"d:\bb.txt", "w", encoding="utf-8")
f.write("一個有溫情的小站\n時間靜止不是簡史")
f.close()

控制台輸出時

問題描述

我們一般習慣把pycharm所有字符編碼設置成utf-8時. 在我們進行網絡請求時, 有時候會返回亂碼問題, 如下圖

問題分析

因為我們在 pycharm 設置所有字符編碼均為 UTF-8, 但是通過網絡請求得到GBK格式的文本, 然後我們仍以 UTF-8 編碼去解碼就會出現亂碼

解決方案

可以將項目編碼設置成GBK格式即可; 也可以通過文本操作代碼對得到的數據進行GBK格式讀取
亦或者在寫入時, 直接將編碼聲明為UTF-8


write()/writelines()寫入數據

  • write(a) :把字符串 a 寫入到文件中
  • writelines(b) :把字符串列表寫入文件中,不添加換行符

實操代碼

# 【操作】添加字符串列表數據到文件中
f = open(r"d:\bb.txt", 'w', encoding="utf-8")
s = ["什麼鬼\n"] * 3 # 通過 \n實現手動換行
f.writelines(s)
f.close()

close()關閉文件流

由於文件底層是由操作系統控制,所以我們打開的文件對象必須顯式調用 close() 方法關閉文件對象.
當調用 close() 方法時,首先會把緩沖區數據寫入文件(也可以直接調用 flush() 方法),再關閉文件,釋放文件對象

注意:

  • close()一般結合異常機制的 finally 一起使用
  • 也可以通過 with 關鍵字實現無論何種情況都能關閉打開的文件對象(推薦)

實操代碼

# 【操作】結合異常機制的 finally ,確保關閉文件對象
# "a" 設置打開方式為追加模式
try:
f = open(r"d:\c.txt", "a")
s = "來自深淵"
f.write(s)
except BaseException as e:
print(e)
finally:
f.close()

with語句(上下文管理器)

with關鍵字 (上下文管理器)可以自動管理上下文資源,不論什麼原因跳出 with塊 ,都能確保文件正確的關閉,
並且可以在代碼塊執行完畢後自動還原進入該代碼塊時的現場

實操代碼

# 【操作】使用 with 管理文件寫入操作
s = ["齊格飛"] * 3
with open(r"d:\cc.txt", "w") as f:
f.writelines(s)

3. 文件的讀取

文件讀取的步驟:

  • 打開文本文件對象
  • 寫入數據

文件的讀取一般使用如下三個方法:

  • read([size]): 從文件中讀取 size 個字符,並作為結果返回
    如果沒有 size 參數,則讀取整個文件. 讀取到文件末尾,會返回空字符串

  • readline(): 讀取一行內容作為結果返回
    讀取到文件末尾,會返回空字符串

  • readlines() : 文本文件中,每一行作為一個字符串存入列表中,返回該列表

代碼格式

with open(r"d:\a.txt", "r"[, encoding="utf-8"]) as f:
f.read(4)

注意:

  • 在讀取文件時, 需要注意讀寫時字符編碼的一致性, 如果寫的時候沒有指定編碼(默認GBK), 則在讀取的時候也不需要指定編碼
  • 但如果讀的時候未指定編碼, 寫的時候指定, 則會報錯.
    例如: 寫的時候指定 encoding="utf-8",
    則控制台報 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 13: invalid start byte

實操代碼

# 【操作】 讀取一個文件前4個字符
import pickle
with open(r"d:\a.txt", "r") as f:
print(f.read(4))
# 【操作】文件較小,一次將文件內容讀入到程序中
with open(r"d:\aa.txt", "r") as f:
print(f.read())
# 【操作】按行讀取一個文件
with open(r"d:\b.txt") as f:
while True:
lines = f.readline()
if not lines: # 在python 中 if not 會將後面對象隱式轉成True或者False進行判斷, 因此遇到空字符串也返回False
break
else:
print(lines, end="")
print()
# 【操作】使用迭代器(每次返回一行)讀取文本文件
# 寫和讀的編碼要對應
with open(r"d:\bb.txt", "r", encoding="utf-8") as f:
for a in f:
print(a, end="")
# 【操作】為文本文件每一行的末尾增加行號
with open(r"d:\c.txt", "r") as f:
lines = f.readlines()
lines2 = [line.rstrip() + " # " + str(index) + "\n" for index, line in zip(range(1, len(lines) + 1), lines)]
with open(r"d:\c.txt", "w") as ff:
ff.writelines(lines2)

二進制文件的讀取和寫入

二進制文件的處理流程和文本文件流程一致。首先還是要創建文件對象,
創建好二進制文件對象後,仍然可以使用 write() 、 read() 實現文件的讀寫操作

在創建文件對象時, 首先需要指定二進制模式,然後才能創建出二進制文件對象. 例如

  • f = open(r"d:\a.txt", 'wb') 可寫的、重寫模式的二進制文件對象
  • f = open(r"d:\a.txt", 'ab') 可寫的、追加模式的二進制文件對象
  • f = open(r"d:\a.txt", 'rb') 可讀的二進制文件對象

實操代碼

# 二進制文件的讀取和寫入(此操作相當於復制)
# f = open(r"d:\a.txt", 'wb') #可寫的、重寫模式的二進制文件對象
# f = open(r"d:\a.txt", 'ab') #可寫的、追加模式的二進制文件對象
# f = open(r"d:\a.txt", 'rb') #可讀的二進制文件對象
with open(r"d:\aaa.png", "rb") as scrFile, open(r"d:\bbb.png", "wb") as destFile:
for l in scrFile:
destFile.write(l)

4. 文件對象的常用屬性和方法

文件對象的屬性

文件對象的打開模式


文件對象的常用方法

文件任意位置操作

利用 seek() 可以將讀取文件的指針移動到指定字節位置上
一個中文字符站兩個字節, 而英文只占一個字節

實操代碼

print("=================文件任意位置操作======================")
# 【示例】 seek() 移動文件指針示例
with open(r"d:\cc.txt", "r") as f:
print("文件名是{0}".format(f.name)) # 文件名是d:\cc.txt
print(f.tell()) # 0
print("讀取文件的內容", str(f.readline())) # 讀取文件的內容 齊格飛齊格飛齊格飛
print(f.tell()) # 18
f.seek(4, 0) # 中文占2個字節, 因此在seek時需要是2的倍數
print("文件讀取的內容", str(f.readline())) # 文件讀取的內容 飛齊格飛齊格飛
print(f.tell()) # 18

三、文件操作拓展模塊

1. pickle序列化模塊

序列化指的是:將對象轉化成“串行化”數據形式,存儲到硬盤或通過網絡傳輸到其他地方.
反序列化是指相反的過程,將讀取到的“串行化數據”轉化成對象
可以使用pickle模塊中的函數,實現序列化和反序列操作

序列化我們使用:

  • pickle.dump(obj, file) obj 就是要被序列化的對象, file 指的是存儲的文件
  • pickle.load(file) 從 file 讀取數據,反序列化成對象

實操代碼

import pickle
print("=================使用pickle序列化=======================")
# 【操作】將對象序列化到文件中
with open("student.info", "wb") as f:
name = "時間靜止"
age = 18
score = [90, 80, 70]
resume = {
"name": name, "age": age, "score": score}
pickle.dump(resume, f)
# 【操作】將獲得的數據反序列化成對象
with open("student.info", "rb") as f:
resume = pickle.load(f)
print(resume)

2. csv文件的操作

csv是逗號分隔符文本格式,常用於數據交換、Excel文件和數據庫數據的導入和導出

與Excel文件不同,CSV文件中:

  • 值沒有類型,所有值都是字符串
  • 不能指定字體顏色等樣式
  • 不能指定單元格的寬高,不能合並單元格
  • 沒有多個工作表
  • 不能嵌入圖像圖表

Python標准庫的模塊csv提供了讀取和寫入csv格式文件的對象

我們在excel中建立一個簡單的表格並且另存為 csv(逗號分隔) ,我們打開查看這個csv文件內容


csv文件讀取

實操代碼

import csv
with open(r"d:\workBook.csv") as a:
o_csv = csv.reader(a) # #創建csv對象,它是一個包含所有數據的列表,每一行為一個元素
headers = next(o_csv) # #獲得列表對象,包含標題行的信息
print(headers)
for row in o_csv: # 循環打印各行內容
print(row)

結果展示

csv文件寫入

實操代碼

# 【操作】 csv.writer 對象寫一個csv文件
headers = ['姓名', '年齡', '工作', '住址']
rows = [('JOJO', '18', '按摩師', '英國'), ('迪奧', '19', '老板', '埃及'), ('喬魯諾喬巴納', '20', '混混', '意呆利')]
with open(r"d:\workBook3.csv", "w") as b:
b_scv = csv.writer(b) # 創建csv對象
b_scv.writerow(headers) # 寫入一行(標題)
b_scv.writerows(rows) # 寫入多行(數據)

結果展示

3. os和os.path模塊

os模塊 可以幫助我們直接對操作系統進行操作.
我們可以直接調用操作系統的可執行文件、命令,直接操作文件、目錄等等
os模塊 是做系統運維非常重要的基礎

os模塊-調用操作系統命令

實操代碼

# 【示例】 os.system 調用windows系統的記事本程序
os.system("notepad.exe")
# 【示例】 os.system 調用windows系統中ping命令
# 如果出現亂碼, 請看 文件操作->文件的寫入->中文亂碼->控制台輸出時 進行配置
os.system("ping www.baidu.com")
# 【示例】運行安裝好的微信
os.startfile(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")

os模塊-文件和目錄操作

可以通過前面講的文件對象實現對於文件內容的讀寫操作.
如果還需要對文件和目錄做其他操作,可以使用 os 和 os.path 模塊.

  • os 模塊下常用操作文件的方法
  • os 模塊下關於目錄操作的相關方法

實操代碼

import os
# 【示例】 os 模塊:創建、刪除目錄、獲取文件信息等
print("系統名稱:", os.name) # windows-->nt linux-->posix
print("當前操作系統所使用的路徑分隔符:", os.sep) # windows-->\ linux-->/
print("行間隔符:", repr(os.linesep)) # windows-->\r\n linux-->\n
print("當前目錄:", os.curdir)
a = "3"
print(a)
# 返回對象的規范字符串表示
print(repr(a))
# 獲取文件和文件夾的相關信息
print(os.stat("MyPy08-FileRead.py"))
# 工作目錄的操作
print(os.getcwd()) # 獲取當前工作目錄
os.chdir("D:") # 切換當前工作目錄
os.mkdir("學習資料大全") # 創建目錄
os.rmdir("學習資料大全") # 刪除目錄
# os.makedirs("人種/黃種人/中國人") # 創建多級目錄, 調用成功一次之後, 再次調用會報錯
# os.rename("人種", "亞洲人") # 此方法也只能調用一次
print(os.listdir("亞洲人")) # 當前目錄下的子目錄

注意事項
在調用 os.rename() 時, 如果出現報錯 PermissionError: [WinError 5] 拒絕訪問,
則需要你在需要重命名的文件夾上面配置用戶的權限. 修改之後便可進行重命名. 如下圖所示


os.path模塊

os.path 模塊提供了目錄相關(路徑判斷、路徑切分、路徑連接、文件夾遍歷)的操作


實操代碼

# 【示例】測試 os.path 中常用方法
print("是否是絕對路徑:", os.path.isabs("d:/a.txt"))
print("是否是目錄: ", os.path.isdir(r"d:\a.txt"))
print("文件是否存在: ", os.path.exists("a.txt"))
print("文件大小: ", os.path.getsize("a.txt"))
print("輸出絕對路徑:", os.path.abspath("a.txt"))
print("輸出所在目錄:", os.path.dirname("d:/a.txt"))
# 獲得創建時間、訪問時間、最後修改時間
print("輸出創建
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved