# IO編程
[TOC]
## 文件讀寫
### 讀文件
```python
try:
# windows下utf8
f = open('./README.md', 'r', encoding='utf8', errors='ignore')
print(f.read())
finally:
f and f.close()
# 用with簡化
with open('./README.md', 'r', encoding='utf8') as f:
print(f.read())
# 迭代讀取大文件
with open('./README.md', 'r', encoding='utf8') as f:
# readline()可以每次讀取一行內容
for line in f.readlines():
# 把末尾的'\n'刪掉
print(line.strip())
# 讀取二進制文件
f = open('/Users/michael/test.jpg', 'rb')
f.read() # b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六進制表示的字節
```
### 寫文件
> 寫文件和讀文件是一樣的,唯一區別是調用open()函數時,傳入標識符'w'或者'wb'表示寫文本文件或寫二進制文件
> 可以反復調用write()來寫入文件,但是務必要調用f.close()來關閉文件。當我們寫文件時,操作系統往往不會立刻把數據寫入磁盤,而是放到內存緩存起來,空閑的時候再慢慢寫入。只有調用close()方法時,操作系統才保證把沒有寫入的數據全部寫入磁盤。忘記調用close()的后果是數據可能只寫了一部分到磁盤,剩下的丟失了。所以,還是用with語句來得保險
```python
with open('./test2.md', 'a', encoding='utf8') as f:
f.write('Hello, python!')
# 文件內字符替換,把你好替換為hi,然后讀取內容到內存中
with open('test.txt','r') as f:
s = f.readlines()
# 接著打開文件,用replace替換掉你內存中的內容,然后寫入文件
with open('test.txt','w') as w:
for i in s:
w.write(i.replace('你好','hi'))
```
## StringIO和BytesIO
### StringIO
在內存中讀寫str。
```python
from io import StringIO
f = StringIO()
f.write('hello')
f.write(' ')
f.write('world!')
print(f.getvalue()) # 方法用于獲得寫入后的str。
f = StringIO('Hello!\nHi!\nGoodbye!')
while True:
s = f.readline()
if(s == ''):
break
print(s.strip())
```
### BytesIO
內存中讀寫bytes
```python
from io import BytesIO
f = BytesIO()
f.write('中文'.encode('utf-8')) # 寫入的不是str,而是經過UTF-8編碼的bytes。
print(f.getvalue())
f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
f.read() # b'\xe4\xb8\xad\xe6\x96\x87'
```
## 操作文件和目錄
```python
import os
os.name # 如果是posix,說明系統是Linux、Unix或Mac OS X,如果是nt,就是Windows系統。
os.uname() # 注意uname()函數在Windows上不提供
```
### 環境變量
在操作系統中定義的環境變量,全部保存在os.environ這個變量中
```python
import os
os.name
'nt'
os.environ # 獲取環境變量
os.environ.get('PATH')
os.environ.get('x', 'default')
```
### 操作文件和目錄
操作文件和目錄的函數一部分放在os模塊中,一部分放在os.path模塊中
```python
# 查看當前目錄的絕對路徑:
os.path.abspath('.')
# 當前的目錄名
os.path.dirname(os.path.abspath(__file__))
# 在某個目錄下創建一個新目錄,首先把新目錄的完整路徑表示出來:
os.path.join('/Users/michael', 'testdir') # '/Users/michael/testdir'
# 然后創建一個目錄:
os.mkdir('/Users/michael/testdir')
# 刪掉一個目錄:
os.rmdir('/Users/michael/testdir')
# 路徑拆分
os.path.split('/Users/michael/testdir/file.txt')
# 獲得文件擴展名
os.path.splitext('/path/to/file.txt')
# 對文件重命名
os.rename('test.txt', 'test.py')
# 刪掉文件
os.remove('test.py')
#OS模塊
#os模塊就是對操作系統進行操作,使用該模塊必須先導入模塊:
import os
#getcwd() 獲取當前工作目錄(當前工作目錄默認都是當前文件所在的文件夾)
result = os.getcwd()
print(result)
#chdir()改變當前工作目錄
os.chdir('/home/sy')
result = os.getcwd()
print(result)
open('02.txt','w')
#操作時如果書寫完整的路徑則不需要考慮默認工作目錄的問題,按照實際書寫路徑操作
open('/home/sy/下載/02.txt','w')
#listdir() 獲取指定文件夾中所有內容的名稱列表
result = os.listdir('/home/sy')
print(result)
#mkdir() 創建文件夾
#os.mkdir('girls')
#os.mkdir('boys',0o777)
#makedirs() 遞歸創建文件夾
#os.makedirs('/home/sy/a/b/c/d')
#rmdir() 刪除空目錄
#os.rmdir('girls')
#removedirs 遞歸刪除文件夾 必須都是空目錄
#os.removedirs('/home/sy/a/b/c/d')
#rename() 文件或文件夾重命名
#os.rename('/home/sy/a','/home/sy/alibaba'
#os.rename('02.txt','002.txt')
#stat() 獲取文件或者文件夾的信息
#result = os.stat('/home/sy/PycharmProject/Python3/10.27/01.py)
#print(result)
#system() 執行系統命令(危險函數)
#result = os.system('ls -al') #獲取隱藏文件
#print(result)
#環境變量
'''
環境變量就是一些命令的集合
操作系統的環境變量就是操作系統在執行系統命令時搜索命令的目錄的集合
'''
#getenv() 獲取系統的環境變量
result = os.getenv('PATH')
print(result.split(':'))
#putenv() 將一個目錄添加到環境變量中(臨時增加僅對當前腳本有效)
#os.putenv('PATH','/home/sy/下載')
#os.system('syls')
#exit() 退出終端的命令
#os模塊中的常用值
#curdir 表示當前文件夾 .表示當前文件夾 一般情況下可以省略
print(os.curdir)
#pardir 表示上一層文件夾 ..表示上一層文件夾 不可省略!
print(os.pardir)
#os.mkdir('../../../man')#相對路徑 從當前目錄開始查找
#os.mkdir('/home/sy/man1')#絕對路徑 從根目錄開始查找
#name 獲取代表操作系統的名稱字符串
print(os.name) #posix -> linux或者unix系統 nt -> window系統
#sep 獲取系統路徑間隔符號 window ->\ linux ->/
print(os.sep)
#extsep 獲取文件名稱和后綴之間的間隔符號 window & linux -> .
print(os.extsep)
#linesep 獲取操作系統的換行符號 window -> \r\n linux/unix -> \n
print(repr(os.linesep))
#導入os模塊
import os
#以下內容都是os.path子模塊中的內容
#abspath() 將相對路徑轉化為絕對路徑
path = './boys'#相對
result = os.path.abspath(path)
print(result)
#dirname() 獲取完整路徑當中的目錄部分 & basename()獲取完整路徑當中的主體部分
path = '/home/sy/boys'
result = os.path.dirname(path)
print(result)
result = os.path.basename(path)
print(result)
#split() 將一個完整的路徑切割成目錄部分和主體部分
path = '/home/sy/boys'
result = os.path.split(path)
print(result)
#join() 將2個路徑合并成一個
var1 = '/home/sy'
var2 = '000.py'
result = os.path.join(var1,var2)
print(result)
#splitext() 將一個路徑切割成文件后綴和其他兩個部分,主要用于獲取文件的后綴
path = '/home/sy/000.py'
result = os.path.splitext(path)
print(result)
#getsize() 獲取文件的大小
#path = '/home/sy/000.py'
#result = os.path.getsize(path)
#print(result)
#isfile() 檢測是否是文件
path = '/home/sy/000.py'
result = os.path.isfile(path)
print(result)
#isdir() 檢測是否是文件夾
result = os.path.isdir(path)
print(result)
#islink() 檢測是否是鏈接
path = '/initrd.img.old'
result = os.path.islink(path)
print(result)
#getctime() 獲取文件的創建時間 get create time
#getmtime() 獲取文件的修改時間 get modify time
#getatime() 獲取文件的訪問時間 get active time
import time
filepath = '/home/sy/下載/chls'
result = os.path.getctime(filepath)
print(time.ctime(result))
result = os.path.getmtime(filepath)
print(time.ctime(result))
result = os.path.getatime(filepath)
print(time.ctime(result))
#exists() 檢測某個路徑是否真實存在
filepath = '/home/sy/下載/chls'
result = os.path.exists(filepath)
print(result)
#isabs() 檢測一個路徑是否是絕對路徑
path = '/boys'
result = os.path.isabs(path)
print(result)
#samefile() 檢測2個路徑是否是同一個文件
path1 = '/home/sy/下載/001'
path2 = '../../../下載/001'
result = os.path.samefile(path1,path2)
print(result)
#os.environ 用于獲取和設置系統環境變量的內置值
import os
#獲取系統環境變量 getenv() 效果
print(os.environ['PATH'])
#設置系統環境變量 putenv()
os.environ['PATH'] += ':/home/sy/下載'
os.system('chls')
# 列出當前目錄文件名
[x for x in os.listdir('.') if os.path.isdir(x)]
# 列出所有的.py文件
[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
# walk返回:tupple(dirpath:路徑, dirnames:該路徑下面的目錄list, filenames: 該路徑下面的文件list)
for fpathe,dirs,fs in os.walk(path):
for f in fs:
print(os.path.join(fpathe,f))
```
> 注意: 不用通過直接拼接字符串的方式,來拆分路徑。這樣可以正確處理不同操作系統的路徑分隔符;