Python 文件操作(IO 技术)

Python 文件操作(IO 技术)

文本文件和二进制文件#

按文件中数据组织形式,我们把文件分为文本文件和二进制文件两大类。

  1. 文本文件
    文本文件存储的是普通“字符”文本,python 默认为 unicode 字符集(两个字节表示
    一个字符,最多可以表示:65536 个),可以使用记事本程序打开。但是,像 word 软件
    编辑的文档不是文本文件。
  2. 二进制文件
    二进制文件把数据内容用“字节”进行存储,无法用记事本打开。必须使用专用的软件
    解码。常见的有:MP4 视频文件、MP3 音频文件、JPG 图片、doc 文档等等

文件操作相关模块概述#

Python 标准库中,如下是文件操作相关的模块

名称 说明
io 模块 文件流的输入和输出操作 input output
os 模块 基本操作系统功能,包括文件操作
glob 模块 查找符合特定规则的文件路径名
fnmatch 模块 使用模式来匹配文件路径名
fileinput 模块 处理多个输入文件
filecmp 模块 用于文件的比较
cvs 模块 用于 csv 文件处理
pickle 和 cPickle 用于序列化和反序列化
xml 包 用于 XML 数据处理
bz2、gzip、zipfile、zlib、tarfile 用于处理压缩和解压缩文件(分别对应不同的算法)

建文件对象 open()#

open()函数用于创建文件对象,基本语法格式如下:

open(文件名[,打开方式])

如果只是文件名,代表在当前目录下的文件。文件名可以录入全路径,比如:D:\a\b.txt。为了减少“\”的输入,可以使用原始字符串:r“d:\b.txt”。示例如下:

f = open(r"d:\b.txt","w")

打开方式有如下几种:

模式 描述
r 读 read 模式
w 写 write 模式。如果文件不存在则创建;如果文件存在,则重写新内容
a 追加 append 模式。如果文件不存在则创建;如果文件存在,则在文件末尾追加内容
b 二进制 binary 模式(可与其他模式组合使用)
+ 读、写模式(可与其他模式组合使用)

文本文件的写入#

文本文件的写入一般就是三个步骤:

  1. 创建文件对象
  2. 写入数据
  3. 关闭文件对象
    【操作】文本写入操作简单测试
f = open(r"day-10.txt", "w", encoding="utf-8")
conten = "你好"
f.write(conten)
f.close()

write()/writelines()写入数据#

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

f = open(r"bb.txt", "w", encoding="utf-8")
f.write("hello\n")
s = ["陈浩\n", "王浩\n", "叶凡\n"]
f.writelines(s)
f.close()

close()关闭文件流#

由于文件底层是由操作系统控制,所以我们打开的文件对象必须显式调用 close()方法关闭文件对象。当调用 close()方法时,首先会把缓冲区数据写入文件(也可以直接调用 flush()方法),再关闭文件,释放文件对象。

为了确保打开的文件对象正常关闭,一般结合异常机制的 finally 或者 with 关键字实现无论何种情况都能关闭打开的文件对象
【操作】结合异常机制 finally 确保关闭文件对象

try:
    f = open(r"day-10.txt", "w")
    content = ["abc\n", "123\n", "ABC\n"]
    f.writelines(c*2 for c in content)

except BaseException as err:
    print(err)

finally:
    f.close()
    print("Done")

# Done

with 语句(上下文管理器)#

with 关键字(上下文管理器)可以自动管理上下文资源,不论什么原因跳出 with 块,都能确保文件正确的关闭,并且可以在代码块执行完毕后自动还原进入该代码块时的现场。

a = ["chenhao\n", "wanghao\n", "yefan"]

with open(r"with1.txt", "w", encoding="utf-8") as f:
    f.writelines(a)

文本文件的读取#

文件的读取一般使用如下三个方法:

  1. read([size])
    从文件中读取 size 个字符,并作为结果返回。如果没有 size 参数,则读取整个文件。读取到文件末尾,会返回空字符串。
  2. readline()
    读取一行内容作为结果返回。读取到文件末尾,会返回空字符串。
  3. readlines()
    文本文件中,每一行作为一个字符串存入列表中,返回该列表。
with open(r"r.txt", "r", encoding="utf8") as f:
    print(f.read())
    print("=" * 50)

with open(r"r.txt", "r", encoding="utf8") as f:
    print(f.read(3))
    print("=" * 50)

with open(r"r.txt", "r", encoding="utf8") as f:
    str = f.readline()
    print(str)
    print("=" * 50)

with open(r"r.txt", "r", encoding="utf8") as f:
    print(f.readlines(), end="\n")
    print("=" * 50)

'''
result:

我的名字是陈浩
我的年龄是18岁
教你爱的人是吗
会是第一吗
大概是多么好看
学会的人是不是越来越少

==================================================
我的名
==================================================
我的名字是陈浩

==================================================
['我的名字是陈浩\n', '我的年龄是18岁\n', '教你爱的人是吗\n', '会是第一吗\n', '大概是多么好看\n', '学会的人是不是越来越少\n']
==================================================
'''

二进制文件的读取和写入#

二进制文件的处理流程和文本文件流程一致。首先还是要创建文件对象,不过,我们需要指定二进制模式,从而创建出二进制文件对象。例如:

f = open(r"d:\a.txt", 'wb') #可写的、重写模式的二进制文件对象

f = open(r"d:\a.txt", 'ab') #可写的、追加模式的二进制文件对象

f = open(r"d:\a.txt", 'rb') #可读的二进制文件对象

创建好二进制文件对象后,仍然可以使用 write()、read()实现文件的读写操作

【操作】 读取图片文件,实现文件的拷贝

with open(r"a.gif", "rb") as f:
    with open(r"b.gif", "wb") as g:
        g.write(f.read())

文件对象的常用属性和方法#

文件对象的属性

属性 说明
name 返回文件的名字
mode 返回文件的打开模式
closed 若文件被关闭则返回 True

文件对象的打开模式

模式 说明
r 读模式
w 写模式
a 追加模式
b 二进制模式(可与其他模式组合)
+ 读写模式(可以其他模式组合)

文件对象的常用方法

方法名 说明
read([size] ) 从文件中读取 size 个字节或字符的内容返回。若省略[size],则读取到文件末尾,即一次读取文件所有内容
readline() 从文本文件中读取一行内容
readlines() 把文本文件中每一行都作为独立的字符串对象,并将这些对象放入列表返回
write(str) 将字符串 str 内容写入文件
writelines(s) 将字符串列表 s 写入文件文件,不添加换行符
seek(offset 把文件指针移动到新的位置,offset 表示相对于 whence 的多少个
[,whence]) 字节的偏移量;
offset:
off 为正往结束方向移动,为负往开始方向移动
whence 不同的值代表不同含义:
0: 从文件头开始计算(默认值)
1:从当前位置开始计算
2:从文件尾开始计算
tell() 返回文件指针的当前位置
truncate([size]) 不论指针在什么位置,只留下指针前 size 个字节的内容,其余全部删除;
如果没有传入 size,则当指针当前位置到文件末尾内容全部删除
flush() 把缓冲区的内容写入文件,但不关闭文件
close() 把缓冲区内容写入文件,同时关闭文件,释放文件对象相关资源

文件任意位置操作#

# e.txt
""""
我的名字是陈浩
我的年龄是18岁
教你爱的人是吗
会是第一吗
大概是多么好看
学会的人是不是越来越少
""""
with open(r"e.txt", "r", encoding="utf-8") as f:
    print(f.name)			# e.txt
    print(f.tell())			# 0
    print(f.readline())		# 我的名字是陈浩
    print(f.tell())			# 23
    print(f.seek(0))		# 0
    print(f.readline())		# 我的名字是陈浩
    print(f.tell())			# 23
    

使用 pickle 序列化#

Python 中,一切皆对象,对象本质上就是一个“存储数据的内存块”。有时候,我们需要将“内存块的数据”保存到硬盘上,或者通过网络传输到其他的计算机上。这时候,就需要“对象的序列化和反序列化”。 对象的序列化机制广泛的应用在分布式、并行系统上。

序列化指的是:将对象转化成“串行化”数据形式,存储到硬盘或通过网络传输到其他地方。反序列化是指相反的过程,将读取到的“串行化数据”转化成对象。

我们可以使用 pickle 模块中的函数,实现序列化和反序列操作。

序列化我们使用:

pickle.dump(obj, file) obj 就是要被序列化的对象,file 指的是存储的文件

pickle.load(file) 从 file 读取数据,反序列化成对

import pickle

a1 = "陈浩"
a2 = 1234
a3 = ["abc", 567, {"key": "value"}]

# 序列化
with open(r"p.dat", "wb") as f:		# 需要以二进制方式写入
    pickle.dump(a1, f)
    pickle.dump(a2, f)
    pickle.dump(a3, f)

# 反序列化
with open(r"p.dat", "rb") as f:		# 需要以二进制方式读取
    b1 = pickle.load(f)
    b2 = pickle.load(f)
    b3 = pickle.load(f)

print("{0}\n{1}\n{2}".format(b1, b2, b3))

"""
result:

陈浩
1234
['abc', 567, {'key': 'value'}]
"""

CSV 文件的操作#

csv文件写入和读取#

import csv

with open(r"emp.csv", "w", newline="") as f:
    row1 = csv.writer(f)
    row1.writerow(["id", "name", "age", "sal"])
    row1.writerow(["0001", "chenhao", "18", "16000"])
    rows = [
        ["0002", "wanghao", "20", "20000"],
        ["0003", "chenfan", "21", "50000"]
    ]
    row1.writerows(rows)

with open(r"emp.csv", "r") as f:
    row2 = csv.reader(f)
    row2_list = list(row2)
    print(row2_list)
    print(f.tell())		# 读取当前指针		86
    f.seek(0)			# 将指针返回初始位置
    print("=" * 40)
    for i in row2_list:
        print(i)
        
"""
result:

[['id', 'name', 'age', 'sal'], ['0001', 'chenhao', '18', '16000'], ['0002', 'wanghao', '20', '20000'], ['0003', 'chenfan', '21', '50000']]
86
========================================
['id', 'name', 'age', 'sal']
['0001', 'chenhao', '18', '16000']
['0002', 'wanghao', '20', '20000']
['0003', 'chenfan', '21', '50000']
"""

os 和 os.path 模块#

os 模块可以帮助我们直接对操作系统进行操作。我们可以直接调用操作系统的可执行
文件、命令,直接操作文件、目录等等。在系统运维的核心基础。

os 模块-调用操作系统命令#

os.system 可以帮助我们直接调用系统的命令

【示例】os.system 调用 windows 系统的记事本程序

import os
os.system("notepad.exe")

【示例】os.system 调用 windows

import os
os.system("ping www.baidu.com")
"""
result:
正在 Ping www.a.shifen.com [111.206.223.206] 具有 32 字节的数据:
来自 111.206.223.206 的回复: 字节=32 时间=9ms TTL=56
来自 111.206.223.206 的回复: 字节=32 时间=7ms TTL=56
来自 111.206.223.206 的回复: 字节=32 时间=6ms TTL=56
来自 111.206.223.206 的回复: 字节=32 时间=9ms TTL=56
111.206.223.206 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 6ms,最长 = 9ms,平均 = 7ms

"""

os.startfile:直接调用可执行文件

【示例】运行安装好的微信

import os
os.startfile(r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe")

os 模块-文件和目录操作#

我们可以通过前面讲的文件对象实现对于文件内容的读写操作。如果,还需要对文件和目录做其他操作,可以使用 os 和 os.path 模块。

os 模块下常用操作文件的方法

方法名 描述
remove(path) 删除指定的文件
rename(src,dest) 重命名文件或目录
stat(path) 返回文件的所有属性
listdir(path) 返回 path 目录下的文件和目录列表

os 模块下关于目录操作的相关方法

方法名 描述
mkdir(path) 创建目录
makedirs(path1/path2/path3/... ) 创建多级目录
rmdir(path) 删除目录
removedirs(path1/path2...) 删除多级目录
getcwd() 返回当前工作目录:current work dir
chdir(path) 把 path 设为当前工作目录
walk() 遍历目录树
sep 当前操作系统所使用的路径分隔符
import os

# 删除指定目录或文件===============================================
os.remove(r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\test01.txt")

# 重命名指定文件或目录===============================================
os.rename("test.txt", "test01.txt")  # os.rename(src:原文件名, dst:新文件名)

# 返回指定文件状态===============================================
stat = os.stat("test.txt01")
print(stat)
# os.stat_result(st_mode=33206, st_ino=3659174697268405, st_dev=2696322469, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1672712784, st_mtime=1672712784, st_ctime=1672712784)

# 返回path目录下的文件和目录列表===============================================
dirs = os.listdir(
    r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os")
print(dirs)
# ['os01.py', 'test.txt01']

# 创建新目录===============================================
os.mkdir(r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\电影")

# 创建多级目录===============================================
os.makedirs(
    r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\音乐\港台\刘德华")

# 删除目录==============================================
os.rmdir(r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\电影")

# 删除多级目录===============================================
os.removedirs(
    r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\音乐\港台\刘德华")

# 查看当前工作目录==============================================
cwd = os.getcwd()
print(cwd)  # C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os

# 更改工作目录==============================================
os.chdir(r"../")    # ../ 返回当前目录上级目录
print(os.getcwd())  # C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10
os.chdir(r"D:")     # 更改为D盘根目录
print(os.getcwd())  # D:\

# 查看当前操作系统===============================================
print(os.name)  # windows->nt linux 和 unix->posix

# 当前操作系统所使用的路径分隔符================================
print(os.sep)  # windows->\ linux 和 unix->/

# 当前操作系统换行符================================================
print(repr(os.linesep))  # windows->\r\n linux-->\n\

# 遍历目录树===============================================
walk = os.walk(r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10")
for i in walk:
    print(i)

"""
result:
('C:\\Users\\chenh\\OneDrive\\Data Learn\\Python 基础\\课堂笔记\\10', ['my_os'], ['a.gif', 'b.gif', 'bb.txt', 'close.py', 'copy_binary.py', 'csv1.py', 'day-10.txt', 'e.txt', 'emp.csv', 'enumerate.py', 'image-20230102205759285.png', 'image-20230102210154753.png', 'image-20230102210404229.png', 'image-20230102210723352.png', 'image-20230102212819694.png', 'open.py', 'os_test.py', 'p.dat', 'pickle1.py', 'Python Basic Day 10.md', 'r.txt', 'read1.py', 'seek.py', 'test.txt', 'with1.py', 'with1.txt'])
('C:\\Users\\chenh\\OneDrive\\Data Learn\\Python 基础\\课堂笔记\\10\\my_os', [], ['os01.py', 'test.txt01'])

"""

os.path 模块#

os.path 模块提供了目录相关(路径判断、路径切分、路径连接、文件夹遍历)的操作

方法 描述
isabs(path) 判断 path 是否绝对路径
isdir(path) 判断 path 是否为目录
isfile(path) 判断 path 是否为文件
exists(path) 判断指定路径的文件是否存在
getsize(filename) 返回文件的大小
abspath(path) 返回绝对路径
dirname(p) 返回目录的路径
getatime(filename) 返回文件的最后访问时间
getmtime(filename) 返回文件的最后修改时间
walk(top,func,arg) 递归方式遍历目录
join(path,*paths) 连接多个 path
split(path) 对路径进行分割,以列表形式返回
splitext(path) 从路径中分割文件的扩展名

【示例】测试 os.path 中常用方法

#测试 os.path 常用方法
import os
import os.path
#################获得目录、文件基本信息######################
print(os.path.isabs("d:/a.txt")) #是否绝对路径
print(os.path.isdir("d:/a.txt")) #是否目录
print(os.path.isfile("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(os.path.getctime("a.txt")) #返回创建时间
print(os.path.getatime("a.txt")) #返回最后访问时间
print(os.path.getmtime("a.txt")) #返回最后修改时间
path = os.path.abspath("a.txt") #返回绝对路径
print(os.path.split(path)) #返回元组:目录、文件
('C:\\Users\\Administrator\\PycharmProjects\\mypro_io\\test_os','a.txt')
print(os.path.splitext(path)) #返回元组:路径、扩展名
('C:\\Users\\Administrator\\PycharmProjects\\mypro_io\\test_os\\a','.txt')
print(os.path.join("aa","bb","cc")) #返回路径:aa/bb/cc

【示例】列出指定目录下所有的.py 文件,并输出文件名

from os import path as p
import os as o


path = o.getcwd()


file_list = o.listdir(path)

for i in file_list:
    if i.endswith("py"):
        print(i, end="\t")  # myospath.py     os01.py


file_list2 = [i for i in o.listdir(o.getcwd()) if i.endswith("py")]

print(file_list2)  # ['myospath.py', 'os01.py']

walk()递归遍历所有文件和目录#

os.walk()方法:

返回一个 3 个元素的元组,(dirpath, dirnames, filenames),

dirpath:要列出指定目录的路径

dirnames:目录下的所有文件夹

filenames:目录下的所有文件
import os

path = os.getcwd()

walk = os.walk(path)
# 返回元组(dirpath, dirnames, filenames)
# dirpath:要列出指定目录的路径
# dirnames:目录下的所有文件夹
# filenames:目录下的所有文件

for dirpath, dirnames, filenames in walk:
    for dir in dirnames:
        print(os.path.join(dirpath, dir))  # 拼接目录路径与其子文件夹
    for file in filenames:
        print(os.path.join(dirpath, file))  # 拼接目录与文件名

zipfile模块压缩与解压#

mport zipfile

z1 = zipfile.ZipFile(
    r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\a.zip", "w")  # 使用写模式创建一个a.zip
z1.write(r"10\my_os\my_walk.py")  # 将my_walk.py写入压缩包
z1.write(r"10\my_os\test01.txt")  # 将test01.txt写入压缩包
z1.write(r"10\my_os\os01.py")  # 将os01.py写入压缩包
z1.close()  # 释放资源

zr = zipfile.ZipFile(
    r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\my_os\a.zip", "r")  # 使用读模式读取a.zip
# 将a.zip全部文件解压到指定目录
zr.extractall(r"C:\Users\chenh\OneDrive\Data Learn\Python 基础\课堂笔记\10\ziptemp")
zr.close()  # 释放资源

递归算法#

递归是一种常见的解决问题的方法,即把问题逐渐简单化。递归的基本思想就是“自己调用自己”,一个使用递归技术的方法将会直接或者间接的调用自己。

利用递归可以用简单的程序来解决一些复杂的问题。比如:斐波那契数列的计算、汉诺塔、快排等问题。

递归结构包括两个部分:

定义递归头。解答:什么时候不调用自身方法。如果没有头,将陷入死循环,也就
是递归的结束条件。

递归体。解答:什么时候需要调用自身方法。

【示例】使用递归求 n!(阶乘)

def factorial(n):
    if n == 1:
        return n
    else:
        return n * factorial(n-1)


print(factorial(10))
# 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
# 3628800

【示例】使用递归算法遍历目录下所有文件

import os

allfiles = []


def getallfiles(path, level):  # path:主目录 # level:缩进
    filenames = os.listdir(path)  # 返回path目录下所有所有子文件与子文件夹
    for file in filenames:
        dir = os.path.join(path, file)  # 将每个(dir)子文件与子文件夹与path目录做拼接
        if os.path.isdir(dir):          # 如果dir是目录为Ture
            getallfiles(dir, level+1)  # 递归:再次调用getallfiles函数,调用自己
        allfiles.append("    "*level+dir)  # 空行 * 缩进 拼接dir 添加到allfiles 列表中


getallfiles(r"C:\Users\chenh\OneDrive\Data Learn", 0)

for i in reversed(allfiles):
    with open("dir.txt", "a", encoding="utf-8") as f:
        f.write(i+"\n")

作者:Hovey

出处:https://www.cnblogs.com/thankcat/p/17020598.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   ThankCAT  阅读(287)  评论(0编辑  收藏  举报
努力加载评论中...
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示