Python的文件操作

文件

文件时操作系统提供给用户/应用程序存取硬盘的一种机制。为了永久保存数据。

操作文件的步骤:

1、打开文件,得到文件句柄并赋值给一个变量。

2、通过句柄对文件进行操作。

3、关闭文件。

在Python中

1、由应用程序向操作系统发起系统调用open(...)。操作系统打开文件返回一个文件对象(或称文件句柄)赋值给变量。

f = open('/PATH/file',mode='[rwa]')

3、调用文件对象的读/写方法,会被操作系统转换为读写硬盘的操作。

f.read()

4、向操作系统发起关闭文件请求,回收系统资源。

f.close()

open()函数

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

file:文件路径,必须传参。

若是Windows系统,传入的路径分隔符为\,可能会出现\n或\t等有特殊意义的字符,可以在字符前面加上r,表示
raw-str原始字符,取消字符的特殊含义。

mode:操作模式。

r(默认的):只读模式。文件不存在则报错,文件存在文件内指针直接跳到文件开头

w:只写模式。在文件不存在时会创建空文档,文件存在会清空文件,文件指针跑到文件开头
	#强调:
		# 1 在文件不关闭的情况下,连续的写入,后写的内容一定跟在前写内容的后面。
		# 2 如果重新以w模式打开文件,则会清空文件内容。

a:追加写模式。在文件不存在时会创建空文档,文件存在会将文件指针直接移动到文件末尾。

+ 模式:r+ w+ a+ :可读可写

w 模式与 a 模式的异同:

1、相同点:在打开的文件不关闭的情况下,连续的写入,新写的内容总会跟在前写的内容之后
2、不同点:以 a 模式重新打开文件,不会清空原文件内容,会将文件指针直接移动到文件末尾,新写的内容永远写在最后。
控制文件读写内容的模式
大前提: tb模式均不能单独使用,必须与r/w/a之一结合使用
t(默认的):文本模式
    1. 读写文件都是以字符串为单位的
    2. 只能针对文本文件
    3. 必须指定encoding参数
    
b:二进制模式:
   1.读写文件都是以bytes/二进制为单位的
   2. 可以针对所有文件
   3. 一定不能指定encoding参数

​ 注意:操作文件时,要注意光标位置,例如写读操作,写操作完光标会在末尾,所以无法读出写入的内容

大前提: tb模式均不能单独使用,必须与r/w/a之一结合使用
可在read()之前,利用seek(0)将光标移动到首部。

encoding:指定字符编码。

如果以t模式操作文件,就要指定字符编码。不指定则为系统默认,Windows为gbk,Linux和Mac为utf-8。
为了保证打开文件不会乱码,写文件和读文件一定要以相同的字符编码。

如果是b模式,一定不要指定encoding。

文件对象内置方法

r模式

read(n):指定读取多少文件,只有在t模式下的read(n)中n表示单位是字符,其他的指针移动单位都是字节bytes。不指定则将文件全部读到内存。读多少个字符指针就会移动多少个字符。

readline():执行一次读取一行内容。

readlines():将文件全部读到内存放入一个列表中。

readable():判断是否可读。

W模式

write():将内容全部写入文件。返回写入的字符数。

writelines():传入一个可迭代对象,每次遍历一个值,写入一个值。值必须是字符串或者bytes类型。

writeable():判断是否可写。

flush():将文件立即写入硬盘。

其他方法

name:查看文件名。

encoding:查看文件编码。

truncate(n):表示保留几个字节,其余部分都删除。utf-8中一个中文占三个字节,如果只保留其中一个或两个字节,最后显示的字符会是乱码。

tell():获取指针所在字节位置。

seek(移动的字节个数,模式):

移动的字节个数:正数表示向右移动,0表示不动,负数表示向左移动。

三种模式:
0:参考文件开头。
1:参考指针当前位置。
2:参考文件末尾。
只有0模式可以在t模式下使用,1和2只能在b模式使用。


# 例如:
f.seek(3,0)  # 表示将指针从文件开头向右移动3个字节。
f.seek(4,1)  # 表示将指针从当前位置向右移动4个字节。
f.seek(5,2)  # 表示将指针从文件末尾向右移动5个字节,指针本就在文件末尾,此时再往右移实际上并没有移动。

资源回收

打开一个文件包含两部分资源:

1、应用程序的变量f。

2、操作系统打开的文件。

在操作完毕一个文件时,必须把文件的这两部分资源全部回收。

# 回收打开的文件
f.close()

# 回收变量资源
del f 

其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件无法关闭,白白占用资源。

python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close(),虽然如此强调,但是用户还是会不由自主地忘记f.close(),考虑到这一点,python提供了with关键字来帮我们管理上下文。

with上下文管理

# 1、在执行完子代码块后,with 会自动执行f.close()
with open('a.txt','w') as f:
    pass 

# 2、可用用with同时打开多个文件,用逗号分隔开即可,如果一行过长可以用转义符\换行。
with open('a.txt','r') as read_f,\
	open('b.txt','w') as write_f:
    data = read_f.read()
    write_f.write(data)
  • 注意:with打开文件在一段时间后会自动关闭句柄,但这个时间不固定。

    如果你在with语句中以r模式打开f1文件,那么你在下面又以a模式打开f1文件,此时有可能你第二次打开f1文件时,第一次的文件句柄还没有关闭,可能会出现错误。

    解决方式只能在你第二次打开此文件前,手动关闭上一个文件句柄。

手动编写一些工具

文件拷贝工具

1、以rb模式向源文件内容读到内存,如果全部读到内存,会占用大量内存空间,文件过大时此操作很危险。

2、以wb模式将源文件内容写入新文件,使用b模式就可以拷贝任意文件。

with open(r'/PATH/source_file',mode='rb') as src_f,\
	open(r'/PATH/target_file',mode='wb') as tar_f:
    while 1:
        line = src_f.read(1024)  # 指定每次读取1024字节,这样就不会占用大量内存空间,但会增加硬盘I/O操作.
        if len(line) != 0:
            tar_f.write(line)
        else:break

文件修改工具

在硬盘中,文件并没有修改的概念。修改文件的本质是将文件读入内存中,修改完毕后再写回硬盘。

方式一

1、以r模式打开源文件,将文件内容全部读到内存。

2、在内存中修改文件。

3、以w模式打开源文件,将修改后的内容写入源文件。

这是编辑器的处理方式,因为要让用户能直接看到全部文件内容。

with open(r'/PATH/file',mode='rt',encoding='utf-8') as f:
    data = f.read()
    ret = data.replace(old,new)  # 指定修改的内容。
with open(r'/PATH/file',mode='wt',encoding='utf-8') as f:
    f.write(ret)

缺点:只能拷贝小文件,如果文件过大会占用大量内存空间。

优点:不会占用大量硬盘空间。

方式二

1、以r模式打开源文件,每次读取文件一行到内存。

2、以w模式创建一个临时文件,每修改完一行内容就写入到临时文件中。

3、修改完毕后,删除源文件,将临时文件改名为源文件。

import os

with open(r'/PATH/old_file',mode='rb') as old_f,\
	open(r'/PATH/.old_file.swp',mode='wb') as new_f:
    for line in old_f:   # 每次读一行内容。
        new_f.write(line)
os.remove('/PATH/.old_file.swp')  # 删除源文件
os.rename('/PATH/new_file','/PATH/.old_file.swp')  # 将临时文件改名为源文件

缺点:硬盘上会同时存在两个相同大小的文件,对硬盘空闲空间有要求。

优点:不会占用大量内存空间。

动态监测文件尾部添加的内容

模拟Linux中tail -f命令。

import time

# 以r模式打开文件,将指针置于文件末尾。
with open('/PATH/file',mode='rt',encoding='utf-8') as f:
    f.seek(0,2)
    while 1:
        last_line = f.readline()  # 不断读下一行.
        if len(last_line) == 0:
            time.sleep(0.1)  # 如果下一行为空,则让程序暂停0.1秒,避免过多消耗CPU。
        else:
            print(last_line,end='')  # 不为空则打印该行。
原文地址:https://www.cnblogs.com/ChiRou/p/13418772.html