文件的基础操作
打开/关闭文件
内建函数open, 能够打开一个指定路径下的文件, 返回一个文件对象.
open最常用的有两个参数, 第一个参数是文件名(绝对路径或者相对路径),
第二个是打开方式, ‘r’/‘w’/‘a’/‘b’,表示读(默认)/写/追加写/二进制
f = open('C:/Users/wyw15/Desktop/test.txt/','r')
f.close()
及时关闭很不容易
def func():
f = open('C:/Users/wyw15/Desktop/test.txt/','r')
# 执行文件操作。。。
x = 10
if x == 10:
return
f.close()
当执行了if语句,这函数就会返回,此时整个函数就有可能会被回收
垃圾回收机制,我们无法确定这个是什么时候能够回收,不可预期
我们不能指望这个机制,我们还需要手动进行回收
修改
def func():
f = open('C:/Users/wyw15/Desktop/test.txt/','r')
# 执行文件操作。。。
x = 10
if x == 10:
f.close()
return
f.close()
即:在每一个能够进行返回的操作中进行关闭文件
缺点:我们的条件会有很多,我们需要在每一个条件下都要进行回收
还有就是一旦条件语句的上面语句出现问题,
我们会直接在那个问题处济宁报错,执行不到 关闭文件语句
此时我们的文件还会一直开
上下文管理器
def func():
with open('C:/Users/wyw15/Desktop/test.txt/','r') as f:
#文件基本操作
pass
读文件
read: 读指定长度字节数的数据, 返回一个字符串.
readline: 读取一行数据, 返回一个字符串, 和for一样
readlines: 读取整个文件, 返回一个列表. 列表中的每一项是一个字符串, 代表了一行的内容.
直接使用 for line in f 的方式循环遍历每一行. 功能和readline类似.
一次只读一行, 相比于readlines占用内存少, 但是访问IO设备的次数会增多, 速度较慢
with open('C:/Users/wyw15/Desktop/test.txt','r') as f:
print(f.readlines())
输出乱码
解决方法:统一编码格式
中文典型编码格式: GBK UTF-8
你的文件是一种编码,代码处理也是一种编码
两种 必须要相互匹配,词汇不乱码
如何知道文件是什么格式?
打开你要操作的文件-》文件-》另存为-》在最下一行的保存左边就是
with open('C:/Users/wyw15/Desktop/test.txt', 'r' ,encoding='utf-8') as f:
print(f.readlines())
['你好世界']
编码在那些环境下会出现,
1.文件存储
2.读取文件和解析过程
3.网络传输,数据格式转换
另外一种读取文件
with open('C:/Users/wyw15/Desktop/test.txt', 'r' ,encoding='utf-8') as f:
for line in f:
print(line)
两种文件读取的差别:
readlines是将文件全部读出来,读到内存中
for 隔一下,读一行,
即readlines读了一下,for读了好多次
readlines 读取速度快,占用内存多–》小文件
for 读取速度慢,占用内存少---------》大文件
注意, readline或者readlines这些函数仍然会保留换行符.
所以我们往往需要写这样的代码来去掉换行符
for line in f.readlines():
print(line.strip())
# 或者
data = [line.strip() for line in f.readlines()] # 还记得我们的列表解析语法嘛
写文件
write: 向文件中写一段字符串.
如需写文件, 必须要按照 ‘w’ 或者 ‘a’ 的方式打开文件. 否则会写失败
with open('C:/Users/wyw15/Desktop/test.txt', 'w' ,encoding='utf-8') as f:
f.write('hehehe')
writelines: 参数是一个列表, 列表中的每一个元素是一个字符串.
并没有一个 writeline 这样的函数. 因为这个动作等价于 write 时在字符串后面加上 ‘\n’.
同理, 使用writelines的时候, 也需要保证每一个元素的末尾, 都带有 ‘\n’
关于读写缓冲区
学习Linux我们知道, C语言库函数中的fread, fwrite和系统调用read, write相比, 功能是类似的. 但是
fread/fwrite是带有缓冲区的.
Python的文件读写操作, 既可以支持带缓冲区, 也可以选择不带缓冲区.
在使用open函数打开一个文件的时候, 其实还有第三个参数, 可以指定是否使用缓冲区, 以及缓冲区的大小
是多少(查看 help(open) 以及 print f.doc ).
使用flush方法可以立即刷新缓冲区
操作文件指针
文件具备随机访问能力. 这个过程是通过操作文件指针完成的.
seek: 将文件指针移动到从文件开头算起的第几个字节上. 有两个参数. 第一个参数offset表示偏移的字节
数. 第二个参数whence表示偏移量的起始位置在哪. 值为0, 表示从开头计算, 值为1, 表示从当前位置, 值为
2, 表示从文件结尾位置.
tell: 获取当前文件指针指向的位置. 返回当前位置到文件开头的偏移量
with语句和上下文管理器
我们刚才说了, 用完的文件对象, 要及时关闭, 否则可能会引起句柄泄露.
但是如果逻辑比较繁琐, 或者我们忘记了手动调用close怎么办?
C++中使用 “智能指针” 这样的方式来管理内存/句柄的释放, 借助对象的构造函数和析构函数, 自动完成释
放过程.
但是Python中对象的回收取决于GC机制, 并不像C++中时效性那么强.
Python中引入了上下文管理器来解决这类问题.
with open('out') as f:
print(''.join(f.readlines()))
在with语句块内进行文件操作. 当文件操作完毕之后, 出了with语句之外. 就会自动执行f的关闭操作.
一个支持上下文协议的对象才能被应用于with语句中. 我们将这种对象称为上下文管理器. Python中很多
内置对象都是上下文管理器, 例如文件对象, 线程锁对象等
代码示例: 基于一个简单文本, 构造一个大文本(构造测试数据)
import sys
input_file_path = sys.argv[1]
output_file_path = sys.argv[2]
output_size = int(sys.argv[3]) * 1024 * 1024
input_file = open(input_file_path)
input_data = input_file.readlines()
output_file = open(output_file_path, 'w')
index = 0
total_size = 0
while True:
if total_size > output_size:
break
output_file.write(input_data[index % len(input_data)])
total_size += len(input_data[index % len(input_data)])
index += 1
文件系统的基础操作
文件路径操作
os.path这个模块中, 包含了一些实用的路径操作的函数
import os.path
p = '/Users/wyw15/Desktop/test.txt'
result = os.path.dirname()
print(result)
分隔
basename() 去掉目录路径,返回文件名
import os.path
p = 'aaa/bbb/ccc.txt'
result = os.path.basename(p)
print(result)
ccc.txt
dirname 去掉文件名,返回目录路径
import os.path
p = 'aaa/bbb/ccc.txt'
result = os.path.dirname(p)
print(result)
aaa/bbb
join 将分离的各部分组合成一个路径名
import os.path
p = 'aaa/bbb/ccc.txt'
result = os.path.split(p) #先用split进行切分
print(f'[{result}]')
# [('aaa/bbb', 'ccc.txt')]
result = os.path.join(p)
print(result)
aaa/bbb/ccc.txt
split 返回(dirname(),basename())元组
import os.path
p = 'aaa/bbb/ccc.txt'
result = os.path.split(p) #先用split进行切分
print(f'[{result}]')
[('aaa/bbb', 'ccc.txt')]
splitdrive 返回(drivename,pathname)元组
splitext 返回(filename,extension)元组----重要
import os.path
p = 'aaa/bbb/ccc.txt'
result = os.path.splitext(p)
print(f'[{result}]')
[('aaa/bbb/ccc', '.txt')]
这是一个元组,如何获取.txt
import os.path
p = 'aaa/bbb/ccc.txt'
_,result = os.path.splitext(p)
print(f'[{result}]')
[.txt]
信息
getatime() 返回最近返回时间
getctime 返回文件创建时间
getmtime 返回最近文件修改时间
getsize 返回文件大小(以字节为单位)
查询
exists 指定路径(文件或目录)是否存在–重要
返回的值是bool
import os.path
p = 'aaa/sss/cc.txt'
print(os.path.exists(p))
# False
pp = 'C:/Users/wyw15/Desktop/test.txt'
print(os.path.exists(pp))
True
isabs 指定路径是否为绝对路径
isdir 指定路径是否存在且为一个目录
import os.path
p = 'C:/Users/wyw15/Desktop/test.txt'
print(os.path.isdir(p))
False
这个是普通文件
isfile 指定路径是否存在且为一个文件
islink 指定路径是否存在且为一个符号链接
ismount 指定路径是否存在且为一个挂载点
samefile 两个路径名是否指向同一个文件
延伸:
修改名字
import os.path as path
常用文件系统操作
os模块中包含了很多对文件/目录的基础操作, 参见下表
文件操作
mkfifo()/mknod() 创建命名管道/创建文件系统节点
remove()/unlink() 删除文件
import os.path
p = 'C:/Users/wyw15/Desktop/test_walk/'
os.remove(p + '11.txt')
此时我们在test_walk 中的文件 11.txt就被删除
rename()/renames() 重命名文件
stst() 返回文件信息
symlink() 创建符号链接
utime() 更新时间戳
tmpfile() 创建并打开(‘w+b’)一个新的临时文件
walk() 生成一个目录树下的所有文件名–重要
i
mport os.path
p = 'C:/Users/wyw15/Desktop/test_walk'
for item in os.walk(p):
print(item)
('C:/Users/wyw15/Desktop/test_walk', ['a', 'b'], [])
('C:/Users/wyw15/Desktop/test_walk\\a', [], ['1.txt', '2.txt'])
('C:/Users/wyw15/Desktop/test_walk\\b', [], ['3.txt', '4.txt'])
因为返回的是一个元组,所以我们可以截取
import os.path
p = 'C:/Users/wyw15/Desktop/test_walk'
for base,_,files in os.walk(p):
for f in files:
print(base + f)
C:/Users/wyw15/Desktop/test_walk\a1.txt
C:/Users/wyw15/Desktop/test_walk\a2.txt
C:/Users/wyw15/Desktop/test_walk\b3.txt
C:/Users/wyw15/Desktop/test_walk\b4.txt
目录/文件夹
chdir()/fchdir() 改变当前工作目录/通过一个文件描述符改变当前工作目录
相当于 cd命令
chroot() 改变当前进程的根目录
listdir() 列出指定目录的文件
想当于ls 功能
import os.path
p = 'C:/Users/wyw15/Desktop/test_walk/'
print(os.listdir(p))
['b']
getcwd()/getcwdu() 返回当前工作目录/功能相同,但发挥一个 Unicode 对象
mkdir()/makedirs() 创建目录/创建多层目录
rmdir()/removedirs() 删除目录/删除多层目录-- python2
现在只能删除空目录
import shutil
p = 'C:/Users/wyw15/Desktop/test_walk/'
shutil.rmtree(p + 'a')
将test_walk 中的a文件删除了
访问/权限
access() 检验权限模式
chmod() 改变权限模式
chown()/lchown() 改变 owner 和 group ID /功能相同,但不会跟踪链接
umask() 设置默认权限模式
文件描述符操作
open() 底层的操作系统open (对于文件,使用标准的内奸 open()函数)
read()/write() 根据文件描述符读取/写入数据
dup()/dup2() 赋值文件描述符号/功能相同,但是是复制到另一个文件描述符