【轉載】Python文件處理

轉載https://blog.csdn.net/weixin_44015805/article/details/99884093

Py文件操作庫及應用(os、sys、pathlib ; open、fileinput、linecache)

# -*- coding: utf-8 -*-
'''
Py文件操作庫及應用.py
(os、sys、pathlib ; open、fileinput、linecache)


深入:


注意:
一、文件編碼解碼問題
open(file,mode='a+', encoding='utf-8')
注意打開模式mode爲帶b的二進制打開模式時的後期輸出時的解碼才能輸出中文問題,且編碼解碼注意一致。


使用:
一、文件系統級操作
1、os
2、sys
3、pathlib       提供了一組面向對象的類,類可代表各種操作系統上的路徑
                 Path類 是 PurePath 的子類,除了支持 PurePath 的各種操作、屬性和方法之外,
                 Path類會真正訪問底層的文件路徑,提供了屬性和方法來訪問底層的文件系統。
二、文件應用級操作
1、open

2、fileinput     迭代一系列文本文件中的所有行。其中input函數,可以把多個輸入流合併在一起,然後進行一些循環操作等
                 fileinput.input()支持從命令行輸入參數 即文件名(多個文件名用 files=[,])
3、linecache     從文件中(所有utf-8文件中)讀取指定行(所有行),並在內部使用緩存優化存儲。
'''



# =============================================================================
# #文件系統級操作
# #(os、sys、pathlib)
# =============================================================================





# =============================================================================
# #os模塊
# #os模塊訪問多個操作系統服務
# #os及其子模塊os.path包含多個查看、創建和刪除目錄及文件的函數,以及一些操作路徑的函數。如os.path.split 和 os.path.join
# =============================================================================

####################
#探索os模塊
import os

help(os)                        #獲取幫助信息
os.__doc__                      #獲取文檔信息
os.__file__                     #獲取源碼文件路徑
os.__all__                      #獲取導入所有名稱列表
os.__name__
dir(os)                         #打印所有 屬性、方法、類。


help(os.environ)                #包含環境變量的映射  如訪問環境變量PATHONPATH,則使用 os.environ['PYTHONPATH]
help(os.system)                 #系統命令  在子shell中執行命令
help(os.sep)                    #路徑中使用的分隔符



####################
#常用的變量、函數、類

#訪問環境變量 PYTHONPATH
os.environ['PYTHONPATH']        #訪問環境變量 PYTHONPATH

#運行命令行命令  直接輸入CMD命令   
os.system('cmd')                #運行命令行命令  直接輸入CMD命令          
os.system('shutdown -s -t 300') #自動關機 300秒後

#打開一個路徑/程序
os.startfile('C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe')


print(os.name)                  # 顯示導入依賴模塊的操作系統的名稱
os.getenv('PYTHONPATH')         # 獲取PYTHONPATH環境變量的值
os.getlogin()                   # 返回當前系統的登錄用戶名
os.getpid()                     # 獲取當前進程ID
os.getppid()                    # 獲取當前進程的父進程ID
os.cpu_count()                  # 返回當前系統的CPU數量
os.sep                          # 返回路徑分隔符
os.pathsep                      # 返回當前系統的路徑分隔符
os.linesep                      # 返回當前系統的換行符
os.urandom(3)                   # 返回適合作爲加密使用的、最多3個字節組成的bytes


####################
#與目錄相關的函數

#獲取當前目錄
os.getcwd()                     #獲取當前目錄

#改變當前目錄到指定目錄
os.chdir('F:/SpyderXIANGMUWENJIANJIA/編程基礎')                    #改變當前目錄到指定目錄

os.getcwd()                     #再次獲取當前目錄

#返回指定目錄下的所有文件和子目錄
os.listdir(os.getcwd())         #返回指定目錄下的所有文件和子目錄


#創建、重命名、刪除等操作
#os.mkdir('os.mkdir測試創建目錄',777)                               #當前目錄下創建子目錄  如果中間目錄爲空則報錯
#os.rename('os.mkdir測試創建目錄','o')                              #重命名當前目錄下的子目錄

#os.makedirs('os.mkdir測試創建目錄1\\遞歸目錄1\\遞歸目錄2',777)      #遞歸創建/a/b/c連環目錄,比mkdir強大
#os.renames('os.mkdir測試創建目錄1\\遞歸目錄1\\遞歸目錄2','a\\b\\c') #遞歸重命名連環目錄

#os.remove('b.txt')             # 刪除文件 b.txt
#os.rmdir('o')                                                     #刪除當前目錄下的子目錄  目錄需要爲空,否則報錯。
#os.removedirs('a\\b\\c')                                          #遞歸刪除連環目錄  如果沒有找到目錄則報錯




####################
#os.path模塊
#os.path模塊提供了操作目錄的方法。

import os,time

print(os.path.abspath('abc.txt'))                                  #獲取絕對路徑
print(os.path.abspath('.'))                                        #獲取當前路徑的絕對路徑
print(os.path.commonprefix(['/usr/lib','/usr/local/lib']))         #獲取共同前綴
print(os.path.commonpath(['usr/lib','usr/local/lib']))             #獲取共同路徑
print(os.path.dirname('abc/xyz/README.txt'))                       #獲取目錄


print(os.path.exists('abc/xyz/README.txt'))                         #判斷指定目錄是否存在
print(time.ctime(os.path.getatime('Py文件庫linecache.py')))         #獲取最近一次訪問時間
print(time.ctime(os.path.getmtime('Py文件庫linecache.py')))         #獲取最後一次修改時間
print(time.ctime(os.path.getctime('Py文件庫linecache.py')))         #獲取創建時間
print(os.path.getsize('Py文件庫linecache.py'))                      #獲取文件大小
print(os.path.isfile('Py文件庫linecache.py'))                       #判斷是否爲文件  # True
print(os.path.isdir('Py文件庫linecache.py'))                        #判斷是否爲目錄  # False
print(os.path.samefile('Py文件庫linecache.py', './Py文件庫linecache.py'))    #判斷是否爲同一個文件  # True



# =============================================================================
# #sys模塊
# #sys模塊訪問與python解釋器緊密相關的變量和函數
# =============================================================================

####################
#探索sys模塊
import sys,pprint                #打印函數,能夠妥善的打印輸出

help(sys)                        #獲取幫助信息
sys.__doc__                      #獲取文檔信息
dir(sys)                         #打印包內所有 變量、函數、類等



help(sys.path)                   #python的搜索路徑的目錄列表,是一個字符串列表,其中每個字符串都是一個目錄名
help(sys.modules)                #將模塊名映射到模塊(僅限當前導入的模塊)

help(sys.exit)                   #退出當前程序。可提供一個整數參數,支出程序是否成功
                                 #應用於 try/finally 異常捕獲時子句依然會執行。
help(sys.argv)                   #獲取命令行輸入參數 sys.argv[]
                                 #包含傳傳遞給python解釋器的參數,包括腳本名,
                                 #可應用於命令行


####################
#常用變量、函數、類

##########
#模塊搜索路徑列表中的 sit-packages目錄 就是專門用來安放模塊的目錄。
print(sys.path)                                      #輸出python的搜索路徑的目錄列表
pprint.pprint(sys.path)                              #格式化打印函數

##########
#程序退出 sys.exit()
'''
sys.exit()會引發一個異常:SystemExit,如果這個異常沒有被捕獲,那麼python解釋器將會退出。
如果有捕獲此異常的代碼,那麼這些代碼還是會執行。捕獲這個異常可以做一些額外的清理工作。
0爲正常退出,其他數值(1-127)爲不正常,可拋異常事件供捕獲。也可添加異常提示信息。

os._exit()會直接將python程序終止,之後的所有代碼都不會繼續執行。
'''
help(sys.exit)
sys.exit.__doc__

#sys.exit('hahaha')                                  #退出程序,並拋出異常。

try:
  sys.exit()
except  SystemExit:                                  #捕獲異常,做一些額外的清理工作。
  print('die')
finally:
  print('這裏通過sys.exit()方法已程序退出,餘下代碼不再執行。')

#import os
#os._exit(0)



####################
#示例1
#sys.argv示例        獲取命令行輸入參數 sys.argv[]

#從命令行輸入命令,   通過提供命令行輸入的參數來執行源碼內容
#命令行輸入格式:     python py文件名 參數1 參數2
  
#sys.argv[]         是用來獲取命令行輸入的參數的(參數和參數之間空格區分),
#sys.argv[0]        參數表示代碼本身文件路徑,所以從參數1開始,表示獲取的參數了
  
'''
參考網址:
https://blog.csdn.net/u013205877/article/details/78571453
'''

#testSys_命令行參數.py
#自建測試文件 testSys_命令行參數.py      輸出命令行參數
import sys
print('執行程序,參數爲{}'.format(sys.argv[1:]))


#testSys_反轉命令行參數.py
#自建測試文件 testSys_命令行參數.py      輸出反向排序的命令行參數

import sys 
args=sys.argv[1:]
args.reverse()
print('反轉參數輸出: ',' '.join(args))     



####################
#示例2
#sys.path應用示例        sys.path.append() 動態修改添加python模塊加載路徑

#scrapy框架爬蟲出現No module named:  的問題
'''
python執行的時候,是根據最初設置的python路徑,
而我們創建的scrapy的路徑不在上面路徑的情況下,導致scrapy找不到路徑,所以把該路徑添加到python執行路徑即可;

添加搜索路徑至python搜索包路徑的目錄列表裏就好,如下,然後重啓程序運行即可。
'''
import os,sys

ffpath = os.path.dirname(os.path.dirname(os.path.abspath(".")))    #獲取目錄名稱os.path.dirname(),獲取絕對路徑os.path.abspath('.')
sys.path.append(ffpath)


# =============================================================================
# #pathlib模塊
# #pathlib模塊提供了一組面向對象的類,這種類可代表各種操作系統上的路徑
# =============================================================================
'''
繼續深入:

參考文檔
https://docs.python.org/3/library/pathlib.html 
'''


import pathlib
from pathlib import *


####################
#探索模塊

help(pathlib)
pathlib.__doc__
pathlib.__file__
pathlib.__all__
dir(pathlib)

help(pathlib.PurePath)    #PurePath類有兩個子類,即 PurePosixPath 和 PureWindowsPath,分別代表 UNIX 風格的路徑(包括 Mac OS X)和 Windows 風格的路徑。;
help(pathlib.Path)        #Path類有兩個子類,    即 PosixPath 和 WindowsPath




####################
#常用屬性、函數、類
'''
pathlib模塊提供的一組面向對象的類,這種類可代表各種操作系統上的路徑。

PurePath類      PurePath類有兩個子類,即 PurePosixPath 和 PureWindowsPath,分別代表 UNIX 風格的路徑(包括 Mac OS X)和 Windows 風格的路徑。;
                PurePath只是代表特定平臺的路徑字符串(它們本質上就是字符串)

Path類          Path類有兩個子類,即 PosixPath 和 WindowsPath
                Path 是 PurePath 的子類,除了支持 PurePath 的各種操作、屬性和方法之外,
                還會真正訪問底層的文件系統,包括判斷 Path 對應的路徑是否存在,獲取 Path 對應路徑的各種屬性(如是否只讀、是文件還是文件夾等),甚至可以對文件進行讀寫。
                PurePath 和 Path 最根本的區別在於,PurePath 處理的僅是字符串,而 Path 則會真正訪問底層的文件路徑,因此它提供了屬性和方法來訪問底層的文件系統。
'''

help(PurePath)         #PurePath類有兩個子類如下:
help(PurePosixPath)
help(PureWindowsPath)

help(Path)             #Path類有兩個子類如下:
help(PosixPath)
help(WindowsPath)




#########
#PurePath類
#PurePath只是代表特定平臺的路徑字符串(它們本質上就是字符串)


#創建PurePath類,在windows系統中實際上使用PureWindowsPath類。
help(PurePath)

pp=PurePath('test.py')
print(type(pp))                                        #如果在 Windows 系統上使用 PurePath 創建對象,程序實際返回 PureWindowsPath 對象。

#PurePath自動組成路徑字符
pp=PurePath('crazyit','some/path','info')              #自動組成路徑字符串    #程序在創建 PurePath 和 Path時,既可傳入單個路徑字符串,也可傳入多個路徑字符串,PurePath 會將它們拼接成一個字符串
pp=PurePath()                                          #無參數則默認創建當前路徑,即點號 .
pp=PurePath(Path('crazyit'),Path('info'))              #等同於上面的創建路徑方法
pp=PurePosixPath('crazyit', 'some/path', 'info')       #明確創建 unix風格 的路徑


#根目錄路徑,只有最後一個生效
pp=PureWindowsPath('c:/windows','d:info')              #如果傳入多個根路徑,則只有最後一個根路徑及後面的子路精生效。  
pp=PureWindowsPath('c:/windows','/program files')      #在windows中只有盤符纔算根路徑

#路徑字符串中多出來的斜槓和點號(代表當前路徑)都會被忽略
#不會忽略兩點..,因爲兩點在路徑中有實際意義(兩點代表上一級路徑)
pp=PurePath('crazyit//info')                           #輸出 crazyit//info
pp=PurePath('crazyit/./info')                          #點被忽略,因爲代表當前路徑。等同於上
pp=PurePath('crazyit/../info')                         #兩個點不被忽略,因爲代表上級目錄
print(pp)


#PurePath類對象的比較運算
#不同風格的 PurePath,unix 和 windows它們依然可以比較是否相等(結果總是返回 False),但不能比較大小,否則會引發錯誤
PurePosixPath('info') == PurePosixPath('INFO')         #unix系統的路徑區分大小寫
PureWindowsPath('info') == PureWindowsPath('INFO')     #windows系統的路徑不區分大小寫
PureWindowsPath('info') in {PureWindowsPath('INFO')}   #注意後面是 set類型集合
PurePosixPath('D:') < PurePosixPath('c:')              #unix系統的路徑區分大小寫,所以返回True
PureWindowsPath('D:') > PureWindowsPath('c:')          #windows系統的路徑不區分大小寫  所以返回True


#斜槓(/)拼接路徑
#將多個路徑連接起來。不管是 UNIX 風格的路徑,還是 Windows 風格的路徑,都是使用斜槓作爲連接運算符
pp=PureWindowsPath('windows:','abc')
print(pp/'xyz')                                        #拼接多個路徑 windows風格

pp2=PurePosixPath('unix:','hehe')                      #拼接多個路徑 unix風格
print(pp2/'haha')                                      

print(pp/pp2)                                          #拼接兩個路徑

#PurePath 的本質其實就是字符串,因此程序可使用 str() 將它們恢復成字符串對象
print(str(pp))




#PurePath類屬性和類方法
'''
類屬性和方法名                    	功能描述
PurePath.parts	                    該屬性返回路徑字符串中所包含的各部分。
PurePath.drive	                    該屬性返回路徑字符串中的驅動器盤符。
PurePath.root	                    該屬性返回路徑字符串中的根路徑。
PurePath.anchor                 	該屬性返回路徑字符串中的盤符和根路徑。
PurePath.parents	                該屬性返回當前路徑的全部父路徑。
PurePath.parent	                    該屬性返回當前路徑的上一級路徑,相當於 parents[0] 的返回值。
PurePath.name	                    該屬性返回當前路徑中的文件名。
PurePath.suffixes               	該屬性返回當前路徑中的文件所有後綴名。
PurePath.suffix	                    該屬性返回當前路徑中的文件後綴名。相當於 suffixes 屬性返回的列表的最後一個元素。
PurePath.stem                   	該屬性返回當前路徑中的主文件名。
PurePath.as_posix()             	將當前路徑轉換成 UNIX 風格的路徑。
PurePath.as_uri()	                將當前路徑轉換成 URI。只有絕對路徑才能轉換,否則將會引發 ValueError。
PurePath.is_absolute()	            判斷當前路徑是否爲絕對路徑。
PurePath.joinpath(*other)	        將多個路徑連接在一起,作用類似於前面介紹的斜槓運算符。
PurePath.match(pattern)	            判斷當前路徑是否匹配指定通配符。
PurePath.relative_to(*other)	    獲取當前路徑中去除基準路徑之後的結果。
PurePath.with_name(name)	        將當前路徑中的文件名替換成新文件名。如果當前路徑中沒有文件名,則會引發 ValueError。
PurePath.with_suffix(suffix)	    將當前路徑中的文件後綴名替換成新的後綴名。如果當前路徑中沒有後綴名,則會添加新的後綴名。
'''
# 訪問drive屬性    
#返回驅動器盤符
print(PureWindowsPath('c:/Program Files/').drive)    #返回驅動器盤符 c:
print(PureWindowsPath('/Program Files/').drive)      #返回驅動器盤符 ''
print(PurePosixPath('/etc').drive)                   #返回驅動器盤符 ''

# 訪問root屬性
#返回路徑字符串中的根路徑
print(PureWindowsPath('c:/Program Files/').root)     #返回路徑字符串中的根路徑 \
print(PureWindowsPath('c:Program Files/').root)      # ''
print(PurePosixPath('/etc').root)                    # /

# 訪問anchor屬性
#返回路徑字符串中的 盤符和根路徑
print(PureWindowsPath('c:/Program Files/').anchor)   # c:\
print(PureWindowsPath('c:Program Files/').anchor)    # c:
print(PurePosixPath('/etc').anchor)                  # /


# 訪問parents屬性
#返回當前路徑的全部福路徑
pp = PurePath('abc/xyz/wawa/haha')
print(pp.parents)
print(pp.parents[0])                                 # abc\xyz\wawa
print(pp.parents[1])                                 # abc\xyz
print(pp.parents[2])                                 # abc
print(pp.parents[3])                                 # .

# 訪問parent屬性
#返回當前路徑的上一級路徑,相當於parents[0]
print(pp.parent)                                     # abc\xyz\wawa


# 訪問name屬性
#返回當前路徑的路徑名
print(pp.name)                                       # haha
pp = PurePath('abc/wawa/bb.txt')
print(pp.name)                                       # bb.txt

#返回文件的所有後綴名
pp = PurePath('abc/wawa/bb.txt.tar.zip')
# 訪問suffixes屬性
print(pp.suffixes[0])                                # .txt
print(pp.suffixes[1])                                # .tar
print(pp.suffixes[2])                                # .zip


#返回文件的最後一個後綴名
# 訪問suffix屬性
print(pp.suffix)                                     # .zip

#返回路徑中的主文件名
print(pp.stem)                                       # bb.txt.tar



#轉成Unix風格的路徑
print(pp.as_posix())                                 # abc/xyz/wawa/haha

#將絕對路徑轉換成uri,只有絕對路徑才能轉換
#將相對路徑轉換成Uri引發異常
#print(pp.as_uri())                                  # ValueError


#創建絕對路徑
pp = PurePath('d:/', 'Python', 'Python3.6')

#將絕對路徑轉換成Uri
print(pp.as_uri()) # file:///d:/Python/Python3.6


#判斷當前路徑是否匹配指定模式
print(PurePath('a/b.py').match('*.py'))              # True
print(PurePath('/a/b/c.py').match('b/*.py'))         # True
print(PurePath('/a/b/c.py').match('a/*.py'))         # False



#創建unix風格絕對路徑
pp = PurePosixPath('c:/abc/xyz/wawa')


#測試relative_to方法
#獲取當前路徑中 去除指定基準路徑 之後的結果
print(pp.relative_to('c:/'))                         # abc\xyz\wawa
print(pp.relative_to('c:/abc'))                      # xyz\wawa
print(pp.relative_to('c:/abc/xyz'))                  # wawa


# 測試with_name方法
#將當前路徑中的主文件名 替換成 指定文件名,若無主文件名則報錯。
p = PureWindowsPath('e:/Downloads/pathlib.tar.gz')
print(p.with_name('fkit.py')) # e:\Downloads\fkit.py

p = PureWindowsPath('c:/')
#print(p.with_name('fkit.py')) # ValueError


# 測試with_suffix方法
#將當前路徑中的 文件後綴名 替換成 指定後綴名,若無則添加後綴名
p = PureWindowsPath('e:/Downloads/pathlib.tar.gz')
print(p.with_suffix('.zip'))  # e:\Downloads\pathlib.tar.zip
p = PureWindowsPath('README')
print(p.with_suffix('.txt'))  # README.txt


##########
#Path類

#Path 是 PurePath 的子類,除了支持 PurePath 的各種操作、屬性和方法之外,
#還會真正訪問底層的文件系統,包括判斷 Path 對應的路徑是否存在,獲取 Path 對應路徑的各種屬性(如是否只讀、是文件還是文件夾等),甚至可以對文件進行讀寫。
#PurePath 和 Path 最根本的區別在於,PurePath 處理的僅是字符串,而 Path 則會真正訪問底層的文件路徑,因此它提供了屬性和方法來訪問底層的文件系統。
'''
繼續深入,參考文檔:
https://docs.python.org/3/library/pathlib.html 
''''

#獲取當前目錄
p=Path('.')

#遍歷當前目錄下所有的 文件和子目錄
for x in p.iterdir():
    print(x)
list(p.iterdir())

#獲取上一級目錄
p=Path('../')

#獲取上級目錄 及其 所有子目錄下的py文件
for x in p.glob('**/*.py'):
    print(x)

#獲取指定對應目錄
p=Path('F:/SpyderXIANGMUWENJIANJIA')

#獲取 上級目錄 及 所有子目錄下的 指定PY文件
for x in p.glob('**/實盤交易.py'):
    print(x)



help(Path)

#創建相對路徑字符串
p = Path('測試文件/testPathlib_A.txt')

#以GBK字符集輸出文本內容
#並實際創建路徑
result = p.write_text('''有一個美麗的新世界
它在遠方等我
那裏有天真的孩子
還有姑娘的酒窩''',  encoding='GBK')

#返回輸出的字符數
print(result)

#指定以GBK字符集讀取文本內容
content = p.read_text(encoding='GBK')

#輸出讀取的文本內容
print(content)

#讀取字節內容
bb = p.read_bytes()
print(bb)



# =============================================================================
# #文件應用級操作
# #(open、fileinput、linecache、pathlib)
# =============================================================================


# =============================================================================
# #open
# #open函數位於自動導入的模塊io中
# =============================================================================


'''
深入:
1、標準輸入輸出等(sys.stdin/sys.stdout/sys.stderr)
可應用管道重定向輸出


注意:
1、文件打開模式,直接決定了後續可以對文件做哪些操作。例如,使用 r 模式打開的文件,後續編寫的代碼只能讀取文件,而無法改動文件內容。
2、read()讀取方法的參數如果省略,則默認一次性讀取所有內容。若參數爲數字,則根據打開模式來區分讀取指定字符/字節。
3、讀取後的文件 可當做 迭代器 來使用,可循環,可操作,可list、序列解包、多重賦值等


使用:
1、打開文件     open()
2、讀取操作     read()、readline()、readlines()
3、寫入操作     write()、writelines()        
4、關閉文件     close()
5、文件指針     tell()、seek()
'''



####################
#打開文件
'''
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

參數file:      要創建或打開文件的文件名稱,該名稱要用引號(單引號或雙引號都可以)括起來。需要注意的是,如果要打開的文件和當前執行的代碼文件位於同一目錄,則直接寫文件名即可;否則,此參數需要指定打開文件所在的完整路徑。
參數mode:      可選參數,用於指定文件的打開模式。可選的打開模式如表 1 所示。如果不寫,則默認以只讀(r)模式打開文件。
參數buffing:   可選參數,用於指定對文件做讀寫操作時,是否使用緩衝區。
'''

help(open)
open.__doc__
dir(open)


#文件打開模式,直接決定了後續可以對文件做哪些操作。例如,使用 r 模式打開的文件,後續編寫的代碼只能讀取文件,而無法改動文件內容。
'''
open 函數支持的文件打開模式
模式	                 意義	                                                        注意事項
r	            只讀模式打開文件,讀文件內容的指針會放在文件的開頭。	操作的文件必須存在。
rb	            以二進制格式、採用只讀模式打開文件,讀文件內容的指針位於文件的開頭,一般用於非文本文件,如圖片文件、音頻文件等。
r+	            打開文件後,既可以從頭讀取文件內容,也可以從開頭向文件中寫入新的內容,寫入的新內容會覆蓋文件中等長度的原有內容。
rb+	            以二進制格式、採用讀寫模式打開文件,讀寫文件的指針會放在文件的開頭,通常針對非文本文件(如音頻文件)。
w	            以只寫模式打開文件,若該文件存在,打開時會清空文件中原有的內容。	若文件存在,會清空其原有內容(覆蓋文件);反之,則創建新文件。
wb	            以二進制格式、只寫模式打開文件,一般用於非文本文件(如音頻文件)
w+	            打開文件後,會對原有內容進行清空,並對該文件有讀寫權限。
wb+	            以二進制格式、讀寫模式打開文件,一般用於非文本文件
a	            以追加模式打開一個文件,對文件只有寫入權限,如果文件已經存在,文件指針將放在文件的末尾(即新寫入內容會位於已有內容之後);反之,則會創建新文件。	 
ab	            以二進制格式打開文件,並採用追加模式,對文件只有寫權限。如果該文件已存在,文件指針位於文件末尾(新寫入文件會位於已有內容之後);反之,則創建新文件。	 
a+	            以讀寫模式打開文件;如果文件存在,文件指針放在文件的末尾(新寫入文件會位於已有內容之後);反之,則創建新文件。	 
ab+	            以二進制模式打開文件,並採用追加模式,對文件具有讀寫權限,如果文件存在,則文件指針位於文件的末尾(新寫入文件會位於已有內容之後);反之,則創建新文件。
'''
#open()
#file=open('a.txt')                          #默認打開模式 r 只讀模式,若無則報錯
file=open('測試文件\\testOpen_A.txt','w+')   #指定打開模式 w+ 爲新建讀寫模式,若無則創建,若存在則替換覆蓋
file.write('這裏是第一次寫入內容')            #write()方法按行寫入內容
#print(file)                                 #通過file.reade()等讀取方法才能輸出內容
file.close()

file=open('測試文件\\testOpen_A.txt',encoding='utf-8')    #指定打開文件的編碼格式,默認爲GBK編碼
#print(file)                                 #通過file.reade()等讀取方法才能輸出內容
file.close()

#open()文件對象常用屬性
file.encoding                                #獲取對象的編碼方式
file.mode                                    #獲取對象的打開模式
file.closed                                  #獲取對象是否處於關閉狀態,返回布爾值
file.name                                    #獲取對象打開的文件名




####################
#文件讀取操作
'''
1、read()             
file.read([size])
其中,file 表示打開的文件對象;
size 作爲一個可選參數,用於指定要讀取的字符個數,如果省略,則默認一次性讀取所有內容。

2、readline()         
file.readline([size])    
file 爲打開的文件對象;
size 爲可選參數,用於指定讀取每一行時,一次最多讀取的字符數。

3、readlines()        
用於讀取文件中的所有行,
它和調用不指定 size 參數的 read() 函數類似,只不過該函數返回是一個字符串列表,其中每個元素爲文件中的一行內容。
和 readline() 函數一樣,readlines() 函數在讀取每一行時,會連同行尾的換行符一塊讀取。
'''

#read()
#參數爲空,則默認讀取全部文件內容
#參數爲1, 則讀取1個字符/字節

#按字節/字符來讀取文件內容
#注意:(打開模式爲 B 二進制則按字節讀取;其他模式則按字符讀取)
f=open('測試文件\\testOpen_A.txt','r',True)
while True:
    ch=f.read(1)                #讀取一個字符,循環一直讀取
    if not ch:                  #如果讀取不到內容,則退出;否則輸出讀取的內容。
        break
#    print(ch)
    print(ch,end='')            #自定義結束字符串味空  以此輸出原文原樣。默認爲換行符
f.close()


#read() #參數爲空,則默認讀取全部文件內容
f=open('測試文件\\testOpen_A.txt','r',True)
print(f.read())
f.close()


#read()後解碼輸出 打開模式爲二進制的bytes對象
f=open('測試文件\\testOpen_A.txt','rb',True)       #用二進制模式打開文件,獲取得到bytes文件對象
#print(f.read())
print(f.read().decode('GBK'))   #open()的默認encoding='GBK',注意需要一致編解碼。
f.close()




####################
#文件寫入操作
'''
1、file.write(string)
其中,file 表示已經打開的文件對象;string 表示要寫入文件的字符串(或字節串,僅適用寫入二進制文件中)。

2、file.writelines()
可以實現將字符串列表寫入文件中
'''

#write()
f=open('測試文件\\testOpen_A.txt','a+')
f.write('\n寫入第二行數據  追加寫入')              #注意 a+爲追加讀寫模式在末尾,注意內容自行添加換行符\n
f.close()


#writelines()寫入列表結構,
#可寫入readlines()讀取返回的列表結構
f=open('測試文件\\testOpen_A.txt','r')
n=open('測試文件\\testOpen_B.txt','w+')
#print(f.readline())
#print(f.readlines())          
n.writelines(f.readlines())                      #readlines()讀取文件中的所有行,返回列表結構。  writelines()寫入列表結構
n.close()
f.close()


#美化輸出
import pprint
pprint.pprint(open('測試文件\\testOpen_A.txt').readlines())





####################
#使用文件的基本方法(讀取/寫入/迭代)

#通過readlines()讀取全部內容成列表後,修改列表元素,然後添加該列表,形成修改後的新的文本文件
f=open('測試文件\\testOpen_A.txt')
lines=f.readlines()      #讀取文件所有行,返回列表結構
f.close()

lines[1]="通過提取f.readlines()的列表,然後對列表進行賦值操作。所以這裏進行了添加和新的修改。"

f=open('測試文件\\testOpen_D.txt','w+')
f.writelines(lines)      #注意 a+爲追加讀寫模式在末尾,添加換行符\n
f.close()

print(lines)



#迭代文件內容的多重方式(read,readline,readlines)
#自建虛構的 內容處理函數
def process(string):
    '''
    用作展示 處理字符或行,可換做其他處理方法
    '''
    print('Processing: ',string)
#通過read方式讀取 單個字符 來循環迭代
with open('測試文件\\testOpen_A.txt') as f:
    char=f.read(1)
    while char:
        process(char)
        char=f.read(1)
with open('測試文件\\testOpen_A.txt') as f:
    while True:
        char=f.read(1)
        if not char:
            break
        print(char,end='')                      #去除輸出結尾的默認換行符,從而達到連續輸出的目的。
#通過readline讀取 單行 來進行循環迭代 
with open('測試文件\\testOpen_A.txt') as f:
    while True:
        char=f.readline()
        if not char:
            break
        process(char)
#通過read 和 readlines 讀取全部內容,來進行循環迭代
with open('測試文件\\testOpen_A.txt') as f:
    for char in f.read():
        process(char)
with open('測試文件\\testOpen_A.txt') as f:
    for char in f.readlines():
        process(char)



#使用fileinput實現延遲 行迭代
import fileinput
for line in fileinput.input('測試文件\\testOpen_A.txt'):
    process(line)



#文件迭代器
#注意:將讀取後的文件當做 迭代器 來使用,可循環,可操作,可list、序列解包、多重賦值等
with open('測試文件\\testOpen_A.txt') as f:
    for line in f:
        process(line)

#在不將 文件對象 賦值給 變量的情況下 迭代文件
for line in open('測試文件\\testOpen_A.txt'):
    process(line)


#對迭代器做的事情基本上都可以對文件做。
#list方法將文件轉換成成字符串列表,效果等同於 readlines
list(open('測試文件\\testOpen_A.txt'))


#通過print的參數file指定,實現對文件近些 寫入操作
f=open('測試文件\\testOpen_E.txt','w')
print('First','line',file=f)                            #輸出內容到指定文件
print('Second','line',file=f)
print('Third','and final','line',file=f)
f.close()


#對文件讀取並序列解包,然後賦值應用
first,second,third=open('測試文件\\testOpen_E.txt')     #給文件內容的每行進行賦值操作
print(first)
print(second)
print(third)





####################
#文件關閉操作
'''
file.close()
如果打開的文件對象不進行close()操作的話,會影響 譬如 os.remove('b.txt') 刪除文件等的操作
'''



####################
#文件指針
'''
實現對文件指針的移動,(以 b 模式打開,每個數據就是一個字節;以普通模式打開,每個數據就是一個字符)文件指針就標明瞭文件將要從文件的哪個位置開始讀起。
tell() 函數用於判斷文件指針當前所處的位置,
seek() 函數用於移動文件指針到文件的指定位置。


file.seek(offset[, whence])
參數whence:  可選參數,用於指定文件指針要放置的位置,
              3 個選擇:0 代表文件頭(默認值)、1 代表當前位置、2 代表文件尾。
參數offset:  表示相對於 whence 位置文件指針的偏移量,正數表示向後偏移,負數表示向前偏移。
              例如,當whence == 0 &&offset == 3(即 seek(3,0) ),表示文件指針移動至距離文件開頭處 3 個字符的位置;
              當whence == 1 &&offset == 5(即 seek(5,1) ),表示文件指針向後移動,移動至距離當前位置 5 個字符處。
'''
f=open('測試文件\\testOpen_A.txt','r')
print(f.tell())            #輸出當前文件指針位置
print(f.read(3))           #按行讀取字符3個字符
print(f.tell())            #輸出當前文件指針位置
f.close() 



f=open('測試文件\\testOpen_A.txt','rb')
print(f.tell())            #輸出當前文件指針位置
print(f.read(1))           #按行讀取1個字節,現文件指針位置在1
print(f.tell())            #輸出當前文件指針位置


f.seek(5)                  #設置文件指針位置至 5   
print(f.tell())            #輸出當前文件指針位置
print(f.read(1))           #按行讀取1個字節
print(f.tell())

#將文件指針位置 向後移動到5個字符的位置
f.seek(5,1)                #單設置文件指針至 當前指針向後移動5個字節 的位置
print(f.tell())
print(f.read(1))
print(f.tell())

#
f.seek(-1,2)               #設置文件指針至 文件結尾向前移動1個字節 的位置
print(f.tell())
print(f.read(1))
print(f.tell())
f.close()







####################
#上下文管理器    同時包含__enter__() 和 __exit__()方法的對象就是上下文管理器
'''
http://c.biancheng.net/view/5319.html
同時包含__enter__() 和 __exit__() 兩個方法的對象就是上下文管理器
__enter__(self)
__exit__(self, exc_type, exc_value, exc_traceback)

構建上下文管理器,常見的有 2 種方式:基於類實現和基於生成器實現。
只要一個類實現了 __enter__() 和 __exit__() 這 2 個方法,程序就可以使用 with as 語句來管理它,
通過 __exit__() 方法的參數,即可判斷出 with 代碼塊執行時是否遇到了異常。
'''
with open('a.txt','a') as f:
    f.write('\nPython大法')


#自定義類   實現上下文管理協議的類,並嘗試用 with as 語句來管理它:
class FkResource:
    '''
    自定義一個實現上下文管理協議的類,並嘗試用 with as 語句來管理它.
    只要一個類實現了 __enter__() 和 __exit__() 這 2 個方法,程序就可以使用 with as 語句來管理它,
    通過 __exit__() 方法的參數,即可判斷出 with 代碼塊執行時是否遇到了異常。
    '''
    def __init__(self,tag):                                       #初始化構造器方法
        self.tag=tag
        print('構造器,初始化資源:{}'.format(tag))
    def __enter__(self):                                          #定義__enter__魔法方法,即with體之前執行的方法
        print('[__enter__方法: {}]'.format(self.tag))
        return 'fkit'                                             #可以返回任何類型來測試該自建類方法
    def __exit__(self, exc_type, exc_value, exc_traceback):       #定義__exit__魔法方法,即with體之後執行的方法
        print('[__exit__方法: {}]'.format(self.tag))
        '''
        參數exc_traceback    爲None,代表沒有異常
        '''
        if exc_traceback is None:                                          
            print('沒有異常,關閉資源')
        else:
            print('遇到異常,關閉資源')
            return False                                          #可以省略,默認返回None也被看成是False

with FkResource('孫悟空') as dr:
    print(dr)
    
 
##測試異常
#with FkResource('白骨精'):
#    print('[with代碼塊]異常之前的代碼////////////////')
#    raise Exception
#    print('[with代碼塊]異常之後的代碼----------------')
    


# =============================================================================
# #fileinput模塊
# #fileinput模塊能夠輕鬆的迭代一系列文本文件中的所有行
# #fileinput模塊提供了input函數,可以把多個輸入流合併在一起,然後進行一些循環操作等

# #可以在命令行運行腳本  命令如:python testNumberlines.py testNumberlines.py
# =============================================================================

####################
#探索fileinput模塊

import fileinput

help(fileinput)
fileinput.__doc__
fileinput.__file__
fileinput.__all__
dir(fileinput)


help(fileinput.filename) 	    #返回正在讀取的文件的文件名。
help(fileinput.fileno)  	    #返回當前文件的文件描述符(file descriptor),該文件描述符是一個整數。
help(fileinput.lineno)   	    #返回當前讀取的行號。
help(fileinput.filelineno)      #返回當前讀取的行在其文件中的行號。

help(fileinput.isfirstline) 	#返回當前讀取的行在其文件中是否爲第一行。
help(fileinput.isstdin)  	    #返回最後一行是否從 sys.stdin 讀取。程序可以使用“-”代表從 sys.stdin 讀取。

help(fileinput.nextfile)	    #關閉當前文件,開始讀取下一個文件。
help(fileinput.close)	        #關閉 FileInput 對象。



####################
#常用屬性、方法、類等
help(fileinput.input)
'''
#fileinput.input(files="filename1, filename2, ...", inplace=False, backup='', bufsize=0, mode='r', openhook=None)
#此函數會返回一個 FileInput 對象
#參數files:       多個文件的路徑序列;
#參數inplace:     用於指定是否將標準輸出的結果寫回到文件,此參數默認值爲 False;
#參數backup:      用於指定備份文件的擴展名;
#參數bufsize:     指定緩衝區的大小,默認爲 0;
#參數mode:        打開文件的格式,默認爲 r(只讀格式);
#參數openhook:    控制文件的打開方式,例如編碼格式等。
'''

#通過input函數創建了 FileInput 對象之後,即可通過 for 循環來遍歷文件的每一行。
#在for循環裏即可通過方法來進行相關操作
'''
#fileinput.filename()	    返回正在讀取的文件的文件名。
#fileinput.fileno() 	    返回當前文件的文件描述符(file descriptor),該文件描述符是一個整數。
#fileinput.lineno() 	    返回當前讀取的行號。
#fileinput.filelineno()	    返回當前讀取的行在其文件中的行號。
#fileinput.isfirstline()	返回當前讀取的行在其文件中是否爲第一行。
#fileinput.isstdin()	    返回最後一行是否從 sys.stdin 讀取。程序可以使用“-”代表從 sys.stdin 讀取。
#fileinput.nextfile()	    關閉當前文件,開始讀取下一個文件。
#fileinput.close()	        關閉 FileInput 對象。
'''



####################
#示例1

'''
不支持中文問題
通過參數打開模式 mode='rb' 即二進制模式打開,然後輸出執行解碼utf-8,輸出中文成功
'''
import fileinput
for line in fileinput.input(files=('testFileinput_A.txt', 'testFileinput_B.txt'),mode='rb'):         # 一次讀取多個文件
    print(fileinput.filename(), fileinput.filelineno(), line.decode('utf-8'))    # 輸出文件名,當前行在當前文件中的行號,行內容。
fileinput.close()                                                # 關閉文件流


with fileinput.input(files=('testA.txt','testB.txt'),mode='rb') as f:
    for line in f:
        print(line.decode('utf-8'))



####################
#示例2         可改寫格式,然後即可用於給文件進行格式添加
        
#自建腳本文件   testFileinput_格式添加.py    在程序右側添加行號格式化

#然後在控制檯運行這個腳本程序,並將其作爲參數傳入。
#命令如:python testFileinput_格式添加.py testFileinput_格式添加.py
'''
出現解碼問題
通過參數打開模式 mode='rb' 即二進制模式打開,然後輸出執行解碼utf-8,輸出中文成功
'''
import fileinput

for line in fileinput.input(mode='rb',inplace=False):         #inplace可選擇是否本地修改
    line=line.rstrip()           #清洗右側空白字符                         
    num=fileinput.lineno()       #輸出當前文件的當前行號
    #print格式設置 冒號前爲輸出對象,冒號後面:整數部分代表寬度,符號<代表左對齊,d代表十進制格式
    print('{:<50} # {:2d}'.format(line.decode('utf-8'),num))    
fileinput.close()



# =============================================================================
# #linecache模塊
#
# #linecache模塊允許從python源文件中(所有utf-8文件)隨機讀取指定行,並在內部使用緩存優化存儲。
# #由於該模塊主要被設計成讀取 Python 源文件,因此它會用 UTF-8 字符集來讀取文本文件。
# #實際上,使用 linecache 模塊也可以讀取其他文件,只要該文件使用了 UTF-8 字符集存儲。
# =============================================================================
'''
#注意:

1、非UTF-8字符集存儲的文件讀取不出來問題。
'''
import linecache
import random

##################
#探索模塊

help(linecache)
linecache.__doc__
linecache.__file__
linecache.__all__
dir(linecache)


help(linecache.getline)          #獲取 文件filename 的 第lineno行 內容   參數(filename,lineno)
help(linecache.getlines)         #獲取 問價filename 的全部行,返回列表結構。

help(linecache.clearcache)
help(linecache.checkcache)



###################
#常用屬性、函數、類

#行數index從1開始,而非0
print(linecache.getline(random.__file__,3))    #讀取random源文件的第三行內容
print(linecache.getlines(random.__file__))     #讀取random源文件的所有行,返回列表結構

#注意非UTF-8字符集存儲的文件讀取不出來問題。
print(linecache.getline('F:\\SpyderXIANGMUWENJIANJIA\\編程基礎\\Py基礎標準庫及應用\Py基礎標準庫time.py',2))
print(linecache.getlines('F:\\SpyderXIANGMUWENJIANJIA\\編程基礎\\Py基礎標準庫及應用\Py基礎標準庫time.py'))

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章