第九章 Python文件操作

I/O (input output 输入输出)是所有程序都必需的能力,使用输入机制允许程序读取外部数据,使用输出机制,允许程序记录运行状态,将数据输出到磁盘等设备。

Python提供了非常丰富的I/O支持,既提供了pathlib和os.path来操作各种路径,也提供了全局的open()函数来打开文件,在打开文件后,程序既可以读取文件的内容,也可以向文件输出内容。

9.1 使用pathlib模块操作目录

pathlib模块提供了一组面向对象的类,这些类可代表各种操作系统上的路径,程序可通过这些类操作路径。

9.1.1 PurePath

PurePath: 代表并不访问实际文件系统的纯路径,只负责对路径字符串进行操作,至于该字符串是否对应实际的路径,并不关心。PurePath有两个子类,PurePosixPath(Unix风格的路径)、PureWindowsPath(Windows风格路径)

例子:

#!usr/bin/python3
from pathlib import *
pp = PurePath("haha.py")
print("type = ", type(pp)) #这行输出type =  <class 'pathlib.PurePosixPath'>,因为mac也是unix 风格
print("pp = ", pp)

pp = PurePath("haha", "hehe", "heihei", "xixi")
print("pp2 = ", pp)

结果:

type =  <class 'pathlib.PurePosixPath'>
pp =  haha.py
pp2 =  haha/hehe/heihei/xixi

如果创建PurePath时不传入参数,系统默认创建代表当前路径的PurePath,相当于传入点号(. 代表当前路径)

#!usr/bin/python3
from pathlib import *
pp = PurePath()
print("pp = ", pp)

结果:

pp =  .

9.1.2 Path

Path是PurePath的子类,它除了支持PurePath的各种操作外,还会真正访问底层的文件系统,包括判断Path对应的路径是否存在,获取Path对应路径的各种属性,甚至可以对文件进行读写

Path同样提供了两个子类:PosixPath和WindowsPath,前者代表Unix风格的路径,后者代表Windows风格的路径

Path对象包含了大量的is_xxx()方法,用于判断Path对应的路径是否为xxx,Path包含一个exists()方法,用于判断该Path对应的目录是否存在

Path还包含一个很常用的iterdir()方法,该方法可以返回Path对应目录下的所有子目录和文件,此外,Path还包含一个glob()方法,用于获取Path对应目录及其子目录下匹配指定模式的所有文件,借助此方法,可以非常方便的查找指定文件

#!usr/bin/python3
from pathlib import *
p = Path(".")
#遍历当前路径下的文件
for x in p.iterdir():
    print("x = ", x)

结果:将当前路径下的文件名都打印了出来

#!usr/bin/python3
from pathlib import *
#获取上一级目录
p = Path("../")
#获取上一级目录及其子目录下的.py文件
for x in p.glob("**/*.py"):
    print("x = ", x)

9.1.3 使用Path读写文件

Path提供了read_bytes()和read_text()方法,分别用于读取该Path对应文件的字节数据(二进制数据)和文本数据,也提供了write_bytes()和write_text()方法来输出字节数据和文本数据,如下所示:

#!usr/bin/python3
from pathlib import *
path = Path("test1.txt")
result = path.write_text("hahahaha\nhehehe", encoding="GBK")
print("result = ", result)

content = path.read_text(encoding="GBK")
print("content = ", content)

b = path.read_bytes()
print("b = ", b)

结果:

result =  15
content =  hahahaha
hehehe
b =  b'hahahaha\nhehehe'

9.2 使用os.path操作目录

在os.path模块下提供了一些操作目录的方法,这些函数可以操作系统的目录本身,该模块提供了exists()函数用于判断该目录是否存在,也提供了其他函数,常用的有如下几个方法:

exists() :  判断文件/目录是否存在

getctime(): 获取该目录的创建时间

getmtime(): 获取该目录最后一次修改时间

getatime(): 获取该目录最后一次访问时间

getsize(): 获取指定文件的大小

isfile(): 判断是否是文件

isdir(): 判断是否是目录

#!usr/bin/python3
import os

file_path = "/Users/haha/Desktop/haha.txt"
print(os.path.exists(file_path))
print("创建时间 = ", os.path.getctime(file_path))
print("最后一次修改时间 = ", os.path.getmtime(file_path))
print("最后一次访问时间 = ", os.path.getatime(file_path))
print("isfile = ", os.path.isfile(file_path))
print("isdir = ", os.path.isdir(file_path))

结果:

True
创建时间 =  1652054926.2842386
最后一次修改时间 =  1652054926.274017
最后一次访问时间 =  1652054926.5356798
isfile =  True
isdir =  False

9.3 打开文件

有了以上内容的铺垫,接下来进入了本章的重点内容,即读写文件

python打开文件使用内置的open函数,f = open("/Users/haha/Desktop/haha.txt", "w") 其中第一个参数表示打开的文件路径,第二个参数w表示访问模式,python提供的访问模式有如下几个:

1. w表示写入(write)

2. r表示读(read)

3. a表示追加模式

4. r+ 和w+都表示读写模式

5. b表示二进制模式,可与其他模式混用,比如rb表示二进制只读模式,rb+表示二进制读写模式

需要注意的是当使用w和w+模式打开文件时,open()函数都会立即清空文件内容,实际上也就无法读取文件内容了,所以如果希望调用open()函数打开文件后,该文件中的内容能被保留下来,那么程序就不能使用w或w+模式了。

还有就是,如果程序使用r或r+模式打开文件,则要求被打开的文件本身是存在的,也就是说使用r或r+模式都不能创建文件,但如果使用w、w+、a、a+模式打开文件,则该文件可以是不存在的,open()函数会自动创建新文件

下图是根据不同场景可以选择的打开模式

 

9.1.1 打开文件的属性

文件打开后,会有一些属性,如获取文件名称、文件编码、访问文件的模式等,如下所示:

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "w")
print("文件编码: ", f.encoding)
print("文件访问模式: ", f.mode)
print("文件是否关闭: ", f.closed)
print("文件名称: ", f.name)

结果:

文件编码:  UTF-8
文件访问模式:  w
文件是否关闭:  False
文件名称:  /Users/haha/Desktop/haha.txt

9.2 文件读取

文件对象提供了read()方法来按字节或者字符串读取文件内容,到底是读取字节还是字符,取决于是否使用了b模式,如果使用了b模式,则每次读取一个字节,如果没有使用b模式,则每次读取一个字符。

9.2.1 普通读取

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "r")
str = f.read() #一次读取文件全部内容
print(str)
f.close()

结果:

haha10
hehe10

9.2.2 一次读取若干个字符

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "r")
while True:
    ch = f.read(1)#参数是1表示一次读取1个字符,参数可以改成其他值
    print(ch, end='')
    if not ch:
        break

f.close()

结果:

哈哈哈
hehehe

上面的程序采用循环的方式依次读取每一个字符,每读取到一个字符,程序就输出该字符,当程序读写完文件后,建议立即使用close()方法来关闭文件,这样可以避免资源泄露。

如果需要更安全的关闭文件,建议将关闭文件的close()方法调用在finally块中执行,如下所示:

9.2.3 使用字节的方式读取

除了二进制文件可以用rb方式读取,读取文本文件也可以,这个和Java中的字节流是一样的,下面看例子

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "rb")
a = f.read().decode("utf-8")
print("a = ", a)

结果:

a =  哈哈哈
hehehe

9.2.4 按行读取

如果程序要按行读取,只能用文本方式来读取,因为只有文本文件才有行的概念,二进制文件没有所谓行的概念

一次读取一行

#!usr/bin/python3
file = open("/Users/bytedance/Desktop/code/ai-ocr/test.txt", "r")
while True:
    #遍历读取每一行
    s = file.readline()
    print("s = ", s)
    if not s:
        break

file.close()

一次读取所有行

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "r")
str = f.readlines()
print("str = ", str)
f.close()

结果:

str = ['haha10\n', 'hehe10\n']

#!usr/bin/python3
file = open("/Users/bytedance/Desktop/code/ai-ocr/test.txt", "r", True)
lines = file.readlines()
for line in lines:
    print(line, end='')

9.2.5 迭代一个文件对象然后读取每行

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "r")
for line in f:
    print(line)
f.close()

结果:

haha10

hehe10

9.2.6 with关键字

使用 with 关键字系统会自动调用 f.close() 方法, with 的作用等效于 try/finally 语句是一样的

#!usr/bin/python3
with open("/Users/bytedance/Desktop/haha.txt", 'r') as file:
    str = file.read()
    print("str = ", str)

结果:

str =  haha10
hehe10

9.3 写文件

如图以r+、w、w+、a、a+模式打开文件,则都可以写入,需要说明的是,当以r+、w、w+模式打开文件时,文件指针位于文件开头处,当以a、a+模式打开文件时,文件指针位于文件结尾处。另外就是,如果以w或w+模式打开文件,程序会立即清空文件的内容。

9.3.1 使用write写文件

#!/usr/bin/python3

f = open("/Users/haha/Desktop/haha.txt", "w")

f.write("hahahaha\nheheheheh\n" )

# 关闭打开的文件
f.close()

结果:写到了文件中

#!usr/bin/python3
file = open("/Users/bytedance/Desktop/code/ai-ocr/test.txt", "wb+")
s = 'hahahah\nhehehe2'
file.write(s.encode("utf-8"))

writelines用法

#!usr/bin/python3
file = open("/Users/bytedance/Desktop/code/ai-ocr/test.txt", "w", True)
file.writelines("hahaha\nheheheh\nxixixi")
file.close()

9.3.2 使用print写文件

#!usr/bin/python3
f = open("/Users/haha/Desktop/haha.txt", "w")
print("hahahahahahahahahah", file=f)
print("hehehehehehehehheh", file=f)

结果:使用print写到了文件中,而不是打印到了控制台

9.3.3 使用追加模式

上面使用w写模式,会将文件内容清空后写入,原来的文件内容保留不了,如果需要在文件末尾追加,则需要用a或a+模式,如下所示:

#!usr/bin/python3
import os
f = open("/Users/bytedance/Desktop/haha.txt", "a+")
f.write("hahaha" + os.linesep)
f.close()

9.4 os模块的文件和目录函数

os模块下也提供了大量操作文件和目录的函数,下面介绍其用法

9.3.1 与目录相关的函数

os.getcwd() : 获取当前目录

os.chdir(path) : 改变当前目录

os.fchdir(fd) : 通过文件描述符改变当前目录

#!usr/bin/python3
import os
print(os.getcwd())

结果:

/Users/haha/source/builder/builder/handler

listdir() :返回指定路径下的文件和文件夹列表

#!/usr/bin/python3

import os
path = "/Users/haha/Desktop"
dirs = os.listdir(path)

for file in dirs:
    print(file)

结果:

展示出path路径下的的所有其他文件或文件夹

mkdir(): 创建目录

makedirs(): 递归创建目录

#!usr/bin/python3
import os
path = "my_dir"
os.mkdir(path, 0o755)
path2 = "abc/xyz/my_dir"
os.makedirs(path2, 0o755)

结果:创建文件夹成功

rmdir(): 删除目录

removedirs(): 递归删除目录

#!usr/bin/python3
import os
path = "my_dir1"
path2 = "abc/xyz/my_dir1"
os.rmdir(path)
os.removedirs(path2)

结果:

删除成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值