天天看點

cp5_1_1.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File  : cp5_1_1.py
# @Author: WRH
# @Date  : 2021/4/7
# @Edition:Python3.8.6

# 第5章:檔案與基于檔案的資料分析
# 5.1檔案的基本概念

# 1.檔案和目錄
'''
檔案是存儲在外部媒體上的資料集合,通常可以長久儲存,也稱為磁盤檔案
檔案是通過目錄來組織和管理的,目錄提供了指向對應磁盤空間的路徑位址
目錄一般采用樹狀結構,在這種結構中,每個磁盤有一個根目錄,它包含若幹檔案和子目錄。
'''

# 2.絕對路徑與相對路徑
'''
絕對路徑:從根目錄開始辨別檔案所在完整路徑的方式成為絕對路徑,任何程式想要對這一檔案進行操作都可以使用此路徑。
相對路徑:相對于程式所在的目錄位置建立其引用檔案所在的路徑,這時儲存在不同目錄下的程式引用這一檔案時所使用的路徑不相同。
        檔案與程式所在的相同的目錄省略
絕對路徑的擷取方法:
方法一:找到檔案所在的檔案夾,單擊選中檔案,按住shift鍵的同時右鍵單擊選擇“複制為路徑”
方法二:找到檔案所在的檔案夾,滑鼠放在頂部位址欄,右鍵選擇”複制位址“,然後在複制的位址後面補上檔案名(包括字尾)
'''
# 例5-1 絕對路徑示例。
'''
檔案workfile.txt儲存在D:盤Pythonlesson目錄的Chapter5子目錄下,那麼包含絕對路徑的檔案名是由
磁盤驅動器、目錄層次和檔案名三部分組成的,即"D:\Pythonlesson\Chapter5\workfile.txt",
為避免遇到轉義符(比如\n)引起路徑錯誤,在Python中用字元串表示為:
"D:\\Pythonlesson\\Chapter5\\workfile.txt""   (\\為反斜杠)
或
"D:/Pythonlesson/Chapter5/workfile.txt" # 用一個/代替\\
'''
# 例5-2 相對路徑示例。
'''
檔案workfile.txt儲存在D:盤Pythonlesson目錄的Chapter5子目錄下,源程式test.py儲存在D:盤的Pythonlesson目錄下,
那麼包含相對路徑的檔案名表示為"Chapter5\workfile.txt",為避免遇到轉義符引起路徑錯誤,
在Python語言中用字元串表示為:
"Chapter5\\workfile.txt"    (\\為反斜杠) 檔案和程式同屬于D:盤Pythonlesson目錄下,是以省略D:\\Pythonlesson\\
或
"Chapter5/workfile.txt"     檔案和程式同屬于D:盤Pythonlesson目錄下,是以省略D:/Pythonlesson/
'''

# 3.檔案的編碼與解碼
'''
a.資料在計算機上的存儲方式是二進制的,即由0和1組成,而我們通常采用兩種方式對其解讀,一種是基于字元編碼,一種是基于值編碼。
  如果某檔案的資料使用基于字元的編碼,那麼該檔案為“文本檔案”,這種檔案通常具有可讀性,例如txt檔案;
  如果某檔案的資料使用基于值的編碼,那麼該檔案為“二進制檔案”,這種檔案通常無法直接讀懂,例如可執行程式、圖形圖像、聲音等等
b.文本檔案可以用win10記事本打開并選擇編碼方式儲存,使用“另存為”指令,在打開的對話框中,
  點選編碼旁邊的倒三角符号可以選擇ANSI、UTF-8等編碼方式進行儲存
c.文本檔案常用的編碼
ASCII (American Standard Code for Information Interchange): 美國資訊交換标準代碼,是一種定長編碼,編碼規則為:
                                                            1位元組 0xxxxxxx (8位)
ANSI:ASCII的擴充版
Unicode:萬國碼,可以容納全世界所有的語言文字嗎,每個字元都有唯一的編碼
Utf-8:針對Unicode的一種可變長度字元編碼。它可以用來表示Unicode标準中的任何字元,而且其編碼中的第一個位元組仍與ASCII相容,
       使得原來處理ASCII字元的軟體無須或隻進行少部份修改後,便可繼續使用,編碼規則可以有1-4個位元組
d.解碼與編碼
Python 3.x版本中,python程式預設使用Unicode進行存儲和編碼,是以使用python程式對文本檔案的資料進行操作時,
通常用unicode編碼作為中間編碼進行轉換。即先将文本檔案中其他編碼的字元串解碼(decode)成unicode,以友善修改,
再将修改後的字元串從unicode編碼(encode)成其他編碼再存儲到文本檔案中。
這一過程同時伴随的是字元串(文本)與位元組流(bytes)的互相轉換。
具體方法如下:

解碼:是把位元組流轉換成字元串,其他編碼格式轉成Unicode,使用bytes.decode()方法
如str1.decode('utf-8'),表示将utf-8編碼的位元組流str1轉化成unicode編碼的字元串。
簡單的來說:解碼就是把位元組流轉化成人看的懂得文字

編碼:是把字元串轉換成位元組流,Unicode格式轉換成其他編碼格式,使用str.encode()方法
如str2.encode('utf-8'),表示将unicode編碼的字元串str2轉化成utf-8編碼的位元組流。
簡單的來說:編碼就是把人看的懂得文字轉化成位元組流
'''

# 例5-3 Unicode編碼與Utf-8編碼之間的轉換示例
s1 = '我發誓學好python'
print(isinstance(s1, str)) # isinstance判斷字元串s1是否是unicode編碼(str),如果是就傳回true,否則傳回false
print(type(s1))
print(s1)

s2 = s1.encode('utf-8') # 将unicode編碼的字元串s1編碼成utf-8編碼,将字元串s1轉換成位元組流
print(s2)
# 将字元串轉換成位元組流(bytes)對象時,對于非ASCII字元,print輸出的是它的字元編碼值(十六進制形式),而不是字元本身。
print(type(s2))
print(isinstance(s2, str)) # 判斷字元串s2是否是unicode編碼(str),如果是就傳回true,否則傳回false

s3 = s2.decode('utf-8') # 将utf-8編碼的字元串s2解碼成unicode編碼,将位元組流s2轉換成字元串
print(s3)
print(type(s3))
print(isinstance(s3, str)) # 判斷字元串s3是否是unicode編碼(str),如果是就傳回true,否則傳回false


# 5.2檔案的操作
'''
程式中對檔案的操作一般包括:
打開檔案
讀取檔案
對檔案資料進行處理
寫入檔案
關閉檔案

python文本檔案的資訊項是字元,二進制檔案的資訊項是位元組。
'''

# 1.檔案的打開與關閉
'''
檔案的打開方法:檔案對象 = open(檔案名 ,模式, encoding='編碼', errors='ignore')
檔案的關閉方法:檔案對象.close()
open()方法傳回了一個檔案對象,括号中通常包含四個字元串類型參數:檔案名、模式、編碼方式、錯誤忽略
檔案名是程式需要操作檔案的完整實體檔案名
編碼即采用何種編碼進行轉化,可省略
錯誤即忽略錯誤直接打開檔案,可省略
模式表示檔案的使用方式,可以省略,省略時預設為r模式,常用的模式具體如下:

模式	含義
r	以隻讀方式打開檔案。檔案的指針将會放在檔案的開頭。這是預設模式。
w	打開一個檔案隻用于寫入。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。
x	寫模式,建立一個檔案,如果該檔案已存在則會報錯FileExistsError。
a	打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。也就是說,新的内容将會被寫入到已有内容之後。
    如果該檔案不存在,建立新檔案進行寫入。
b	表示二進制模式,添加在其他控制字元後。
t	文本模式 (預設)。
+	打開一個檔案進行更新(可讀可寫)。

rb	以二進制格式打開一個檔案用于隻讀。檔案指針将會放在檔案的開頭。這是預設模式。一般用于非文本檔案如圖檔等。
r+	打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。
rb+	以二進制格式打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。一般用于非文本檔案如圖檔等。

wb	以二進制格式打開一個檔案隻用于寫入。如果該檔案已存在則打開檔案,并從開頭開始編輯,
    即原有内容會被删除。如果該檔案不存在,建立新檔案。一般用于非文本檔案如圖檔等。
w+	打開一個檔案用于讀寫。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。如果該檔案不存在,建立新檔案。
wb+	以二進制格式打開一個檔案用于讀寫。如果該檔案已存在則打開檔案,并從開頭開始編輯,即原有内容會被删除。
    如果該檔案不存在,建立新檔案。一般用于非文本檔案如圖檔等。

ab	以二進制格式打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。
    也就是說,新的内容将會被寫入到已有内容之後。如果該檔案不存在,建立新檔案進行寫入。
a+	打開一個檔案用于讀寫。如果該檔案已存在,檔案指針将會放在檔案的結尾。檔案打開時會是追加模式。
    如果該檔案不存在,建立新檔案用于讀寫。
ab+	以二進制格式打開一個檔案用于追加。如果該檔案已存在,檔案指針将會放在檔案的結尾。如果該檔案不存在,建立新檔案用于讀寫。
'''
# 例5-4 打開與關閉檔案示例
# 第一種方法,使用os子產品切換到程式所要操作的檔案所在的目錄進行打開與關閉
import os # 導入python内置子產品os,此子產品用于處理檔案和目錄
os.chdir('D:\\Pythonlesson\\Chapter5')
# os.chdir(path)函數:改變目前工作目錄,path内容為所要操作檔案所在的目錄
f = open('workfile.txt', 'r')
# 使用open()方法以隻讀方式打開workfile檔案,傳回一個檔案對象并指派為f。
f.close() # 關閉檔案

# 第二種方法,直接使用絕對路徑進行打開與關閉
f = open('D:\\Pythonlesson\\Chapter5\\workfile.txt', 'r')
f.close()

# 第三種方法,當且僅當程式和程式要操作的檔案在同一檔案夾,可直接對檔案進行打開與關閉
f = open('workfile.txt', 'r')
f.close()

# 2.對檔案内容進行定位操作
'''
通過open()方法建立了一個檔案對象後,讀/寫指針會定位在檔案的頭部,即最左邊的開始位置,然後檔案中的資訊将按照
從左到右的順序被通路,這稱為順序存取。如果要對檔案中的自定義位置進行随機讀/寫,可以使用seek()方法。
seek()方法格式如下:
f.seek(偏移值, 起始位置)
偏移值:表示從起始位置再移動一定量的距離,偏移值為正數表示向右(即檔案尾部方向)移動為負數表示向左(即檔案頭部方向)移動。
       當起始位置為1或2時,隻有二進制模式可以指定非0的偏移值。偏移值的機關是位元組(Byte),每兩個位元組為一個字元。
起始位置:為0表示自檔案起始處開始(預設值,當有偏移值 時可省略),1表示從目前檔案指針位置開始,2表示從檔案末尾開始。
'''
# 例5-5 随機通路二進制檔案示例。
import os # 導入python内置子產品os,此子產品用于處理檔案和目錄
os.chdir('d:\\Pythonlesson\\Chapter5') # os.chdir(path)函數:改變目前工作目錄,path内容為所要操作檔案所在的目錄
f = open('workfile.txt', 'rb+') # rb+ 以二進制格式打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。
f.write(b'I like Python !') # f.write()方法将字元串string(或位元組流bytes)的内容寫到對象f對應的檔案中
print(f.seek(2)) # 指針從檔案開始位置向右偏移2個位元組,并輸出指針所在位置
print(f.read(4)) # 從指針位置向右開始讀取4個位元組内容并輸出
print(f.seek(-8, 2)) # 指針從檔案末尾位置向左偏移8個位元組,并輸出指針所在位置
print(f.read(6)) # 從指針位置向右開始讀取6個位元組内容并輸出
f.close() # 關閉檔案

# 例5-6 随機通路文本檔案示例。
import os
os.chdir('d:\\Pythonlesson\\Chapter5')
f = open('workfile2.txt', 'r+') # r+ 打開一個檔案用于讀寫。檔案指針将會放在檔案的開頭。
f.write('我發誓要好好學Python') # 将字元串'我發誓要好好學Python'寫到對象f對應的檔案workfile2.txt中
f.seek(8) # 指針從檔案開始位置向右偏移8個位元組,每兩個位元組對應一個字元。
print(f.read(9)) # 從指針位置向右開始讀取9個字元内容并輸出
#f.seek(-8, 2) # 當起始位置為1或2時,隻有二進制模式可以指定非0的偏移值
#f.seek(3, 1)
f.seek(0, 2) # 指針從檔案末尾位置向右偏移0個位元組
f.seek(0, 1) # 指針目前位置向右偏移0個位元組
f.close() # 關閉檔案

# 3.檔案的讀取、寫入、追加

# 讀取
# f.read(size)方法
'''
該方法傳回一個字元串,内容為長度為size的文本。數字類型參數size表示讀取的字元數,可以省略。
如果省略size參數,則表示讀取檔案所有内容并傳回。如果指針已到達檔案的末尾,f.read()将傳回一個空字元串('')
'''
import os
os.chdir('D:\Pythonlesson\Chapter5')
f = open('workfile3.txt', encoding='utf-8')
# 國内Windows10系統下預設使用gbk(《漢字内碼擴充規範》)編碼,如果檔案内容含有中文或某些特殊字元,
# 對檔案進行更改時會報UnicodeDecodeError(編碼錯誤),這裡添加encoding = 'utf-8'進行更改編碼
print(f.read()) # 輸出檔案全部内容,兩行字元,一行空格
print(f.read()) # 指針到達檔案末尾,輸出空字元''

# f.readline()方法
'''
該方法傳回一個字元串,内容為檔案的目前一行。換行符(\n)留在字元串的末尾。
如果已到達檔案的末尾,f.readline()将傳回一個空字元串('')。如果是一個空行,則傳回'\n'
'''
f.seek(0) # 指針回到檔案開始處
print(f.readline()) # 輸出第一行
print(f.readline()) # 輸出第二行
print(f.readline()) # 輸出第三行,第三行是空行

# 從檔案中讀取行,更高效的是在檔案對象上循環
f.seek(0)
for line in f:
    print(line)

# f.readlines()方法
'''該方法傳回一個清單,清單中的每個字元串類型元素對應檔案的每行(包括結尾的換行符“\n”)'''
f.seek(0)
print(f.readlines()) # 輸出全部内容,指針到達末尾
print(f.readlines()) # 指針在末尾,後面沒有内容,輸出空清單
f.close()

# 快速清單讀取:清單 = list(open(檔案名, 模式, 編碼, 錯誤忽略))
L = list(open('workfile3.txt', encoding='utf-8'))
print(L)

# 寫入
# f.write(string)方法
'''
将字元串string的内容寫到f對應的檔案中,并傳回寫入的字元數。
但write語句不會自動換行,如果需要換行,則要使用換行符\n。
\n代表一個字元。以w模式打開的檔案的原有内容将被覆寫,如果檔案不存在将建立此檔案。
'''

import os
os.chdir('D:\Pythonlesson\Chapter5')
f = open('workfile4.txt', 'w', encoding='utf-8')
f.write('人生苦短\n')
f.seek(0)

# 追加
import os
os.chdir('D:\Pythonlesson\Chapter5')
f = open('workfile4.txt', 'a', encoding='utf-8')
# 以a模式打開檔案,指針會移到末尾處,寫入的内容将追加到該檔案的末尾
f.write('我用Python!\n')