0 前言
最近一直在与数据集的读取和处理打交道,不可避免的会用到python中文件处理的知识点,有些函数和知识点虽然知道是怎么回事,但是感觉掌握的还不是很牢靠,因此打算整理一下知识点,方便以后自己查看。
1 os模块
在os模块下有很多文件处理的指定,比如文件的读取和写入等命令,下面就简单介绍几个常见的命令。
(1) 打开文件
# open()函数签名
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
- file表示你要打开的文件地址,文件地址有相对路径和绝对路径之分,在open函数中你都可以使用。
- mode表示你要对文件进行怎样的操作。常见的有下面几种方式:
'r'表示仅读取文件内容,如果你向文件中写入数据的话,会报错 'io.UnsupportedOperation: not writable'
'w'表示先清空文件内容,然后再写入数据
'a'表示在原文的末尾追加数据
模式'w+'和'w+b'表示将打开文件并清空文件内容。模式'r+'与'r+b'表示打开文件内容但是并不清空内容,这表示你可以对文件内容进行更新,可以写入或者更改内容,并不会报错。模式'a+'与'a+b'表示打开文件让后在后面追加内容。
-
encoding表示你采用什么样的编码格式。如果读取或者写入的是中文字符,可以设置成'utf-8'的编码格式。
(2) 读取文件
打开文件之后,我们可以使用一下三种方法读取文件的内容
-
read()函数:函数的返回值是一个字符串,因此你可以配合字符串函数进行读取并处理。
with open('./test.txt') as f:
content = f.read()
# 可以配合split()函数将内容进行分割
content1 = f.read().split('/n')
- readlines()函数:函数的返回值是一个列表,列表的每个元素是原文件每一行的数据。
with open('./test.txt') as f:
lines = f.readlines()
# 可以循环索引列表中的内容,并进行打印
lies = [int(i) for i in lines]
- readline()函数:每次值读取一行数据内容,可以配合循环函数使用,这个占用内存比较小,因此可以应用在读取内容比较多的文件。
with open('./test.txt') as f:
while True:
line = f.readline()
if len(line):
print(line)
# 读取结束
else:
break
(3) 写入数据
write()函数可以向文件中写入字符串数据(注意一定是字符串数据)
with open('./test.txt') as f:
# 向文件中写入数据
f.write('hello world')
(4) 获取某个路径下所有的文件地址和文件夹地址
在处理数据集的时候,我需要获得训练集下所有xml文件的地址,对其进行读取。因此可以使用一下几种方法:
-
os.walk()函数
# 函数签名
os.walk(top, topdown=True, onerror=None, followlinks=False)
os.walk()函数可以获得某个路径下所有的文件和文件夹地址,下面通过一个案例来说明:
# step1: '../data'文件的目录是这样的
---- data
---- obj
---- image1.jpg
---- image1.xml
---- obj.data
---- obj.names
# step2: 遍历文件夹,然后打印
for root_path, sub_dir_path, files_path in os.walk('../data'):
# (1)打印root_path:结果是'../data'和'../data/obj'
print(root_path)
# (2) 打印sub_dir_path: 结果是['obj']和[]
print(sub_dir_path)
# (3)遍历files_path列表中所有xml文件: 打印结果['image1.xml']
for file_path in files_path:
if file_path.endswith('xml'):
print(file_path)
root_path表示要遍历的文件夹地址,在案例中是'../data'和'./data/obj'。因为该文件夹下仍然存在文件夹,所以依然会对子文件夹进行遍历。
sub_dir_path表示当前文件夹下的子文件夹名称,如果子文件夹中还存在文件,依然循环打印其子文件名称。
files_path表示当前文件夹下文件的名称,如果子文件夹中存在文件,依然将其子文件中的子文件放在列表中进行打印。
- os.listdir()函数
os.listdir()函数可以获得某个文件夹下所有文件和文件夹的名称(不是地址)
for path in os.listdir('../data'):
print(path)
# 输出结果就是
# obj
# obj.data
# obj.names
(5) 拼接路径
在使用os.walk()函数的时候,我们可以获得文件夹的路径以及文件的名称,而在数据集中,我们需要保存文件的绝对路径或者是包含当前根目录的相对路径,因此我们就需要对文件地址进行拼接。
在拼接路径的时候,我们可以使用下面os.path.join()函数,下面说明了使用该函数的注意点(借鉴了这位老哥的博客)
os.path.join()函数:连接两个或更多的路径名组件
1.如果各组件名首字母不包含’/’,则函数会自动加上
2.如果有一个组件是一个绝对路径,则在它之前的所有组件均会被舍弃
3.如果最后一个组件为空,则生成的路径以一个’/’分隔符结尾
# 案例1:如果各组件名首字母不包含’/’,则函数会自动加上
path1 = 'home'
path2 = 'develop'
path3 = 'code'
print(os.path.join(path1,path2,path3))
# 输出是:
# home\develop\code
# 案例2:如果有一个组件是一个绝对路径,则在它之前的所有组件均会被舍弃
# 这一点一定要注意!!!!!
path1 = 'home'
path2 = '/develop'
path3 = 'code'
print(os.path.join(path1,path2,path3))
# 输出是:
# /develop/code
# 案例3:如果最后一个组件为空,则生成的路径以一个’/’分隔符结尾
path1 = '/home'
path2 = 'develop'
path3 = ' '
print(os.path.join(path1,path2,path3))
# 输出是:
# /home/develop/