python文件处理

python文件处理


一、文件操作

1.1、基础流程

# 1、打开文件,由引用程序向系统发起系统调用open(),操作系统打开文件对应的磁盘空间,并赋值给一个变量f
f = open('a.txt', encoding='UTF-8')

# 2、调用文件对象的读方法,
date = f.read()

# 3、输出文件内容
print(date)

# 4、关闭文件,向操作系统发起关闭文件的请求,回收系统资源
f.close()

1.2、资源回收与with上下文管理

打开一个文件包含两部分资源:应用程序的变量 f 和操作系统打开的文件。在操作完毕一个文件的时候,必须把与该文件相关的这两部分资源回收掉,回收方法为:

# 回收操作系统打开的文件资源
f.close()

# 回收应用程序的变量
del f

del f 一定要发生在 f.close() 之后,否则就会导致操作系统打开的文件无法关闭,浪费资源
而python的垃圾回收机制决定了我们无需考虑 del f
这就要求我们操作完成文件之后,一定要记住 f.close()
但是虽然关闭文件如此重要,但是我们还是会忘记,因此,Python提供了 with 关键字来帮助我们管理上下文

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

# 2、可以用with同时打开多个文件,使用逗号分割
with open('a.txt', 'r') as f_a, open('b.txt', 'r') as f_b:
    data = f_a.read()
    print(data)
    print()
    data = f_b.read()
    print(data)

1.3、指定操作文件的字符编码

open() 是由操作系统打开文件,如果打开的是文本文件,会涉及到字符编码的文艺,如果没有为open()指定编码,那么操作系统会使用自己的默认字符编码去操作文件;
如果要保持不乱码,文件以什么方式存储的,就要以什么方式打开

f = open('a.txt', encoding='UTF-8')
data = f.read()
print(data)
f.close()

二、文件的操作模式

2.1、控制文件读写的模式

  • r 只读模式(默认)
  • w 只写模式
  • a 只追加写

只读模式

with open('a.txt', encoding='UTF-8') as f:
    data = f.read()
    print(data)

只写模式

# 文件不存在时会创建空文档,文件存在时会清空文件,文件指针指向文件开头
with open('a.txt', 'w')as f:
    f.write('你好\n')
    f.write('我是\n')
    f.write('大家好\n')
    f.write('111\n222\n333\n')

追加模式

# 文件不存在时会创建空文件件,文件存在时会讲文件指针指向文件末尾
with open('a.txt', 'a')as f:
    f.write('卧室\n')
    f.write('121\n232\n343\n')

读写模式

方式 说明
r+ 文件指针指向文件开头,如果文件不存在则爆出异常
w+ 如果文件存在则会被覆盖,如果文件不存在则创建新文件
a+ 文件指针指向文件末尾,如果文件不存在则创建新文件

2.2、控制文件读写内容模式

t/b模式均不能单独使用,必须与r/w/a之一结合使用

t 文本模式

# 如果我们打开文件指定的是r/w/a,那么其默认就是rt/wt/at
with open('a.txt', 'rt') as f:
    data = f.read()
    print(data)

with open('a.txt', 'wt') as f:
    indata = 'df'
    f.write(indata)

b 二进制模式

with open('a.txt', 'wb') as f:
    msg = "hello"
    indata = msg.encode('UTF-8')
    f.write(indata)



with open('a.txt', 'rb') as f:
    data = f.read()
    print(type(data))

<class 'bytes'>

模式对比

1、在操作纯文本文件方面t模式帮我们省去了编码与解码的环节,b模式则需要手动编码与解码,所以此时t模式更为方便
2、针对非文本文件(如图片、视频、音频等)只能使用b模式
3、在b模式不能用encoding来指定编码

拷贝demo

src_file = input('源文件路径').strip()
dst_file = input('目标文件路径').strip()

with open(f'{src_file}', 'rb') as src_f, open(f'{dst_file}', 'wb') as dst_f:
    for line in src_f:
        dst_f.write(line)

三、操作文件的方法

方法解释

文件对象方法 说明
f.read() 有参数表从开头读多少个字节,没有读取所有内容。读小文件推荐
f.readline() 读取一行内容,光标移动到第二行首部.读大文件推荐,或者 for line in 遍历
f.readlines() 读取每一行内容,存放于列表中.返回值是一个列表包含'\n'.读小文推荐
f.write() f.write('1111\n222\n') #针对文本模式的写,需要自己写换行符。内容必须是 字符串
f.write() f.write('1111\n222\n'.encode('utf-8')) #针对b模式的写,需要自己写换行符。返回是int 字符数
f.writelines() f.writelines(['333\n','444\n']) #文本模式。列表元素必须是 字符串
f.writelines() f.writelines([bytes('333\n',encoding='utf-8'),'444\n'.encode('utf-8')]) #b模式
f.seek(x,y) seek(x, 0):从开始位置向右 x 个字符
f.seek(x,y) seek(x, 1):当前位置往右移动 x 个字符
f.seek(x,y) seek(-x, 2):文件的结尾向左移动 x 个字符
f.tell() 返回文件的当前位置
f.truncate() 清空文件,配合f.seek(0) 使用,调整指针位置
f.closed 文件是否关闭
f.flush() 立刻将文件内容从内存刷到硬盘
f.readable() 文件是否可读
f.writable() 文件是否可写
f.name 文件名字

3.1、读操作

# 读取所有内容,执行完读取操作后,文件指针指向文件末尾
f.read()

# 读取一行内容,执行完读取操作后,文件指针指向第二行首
f.readline()

# 读取每一行内容,存放到列表中
f.readlines()

f.read() 和 f.readlines() 都是一次性读取所有内容,如果内容过大会导致内存溢出,如果需要读取大文件,可以分次读入

方式一

# 同一时刻只读取一行内容到内存里

with open('a.txt', 'rt', encoding='UTF-8') as f:
    for line in f:
        print(line)

方式二

# 同一时刻只读取1024个Bytes到内存中

with open('a.txt', 'rb') as f:
    while 1:
        data = f.read(1024)
        if len(data) == 0:
            break
        print(data)

3.2、写操作

f.write('1111\n222\n333')
f.write('www\neee\n'.encode('UTF-8'))
f.writelines(['111\n', '222\n', '333'])
f.writelines([bytes('333\n',encoding='UTF-8'),'sss\n'.encode('UTF-8')])

3.3、seek:控制文件内指针的移动

文件内指针的移动都是以Bytes为单位的,只有在t模式下的f.read(n),此时 n 的单位是字符,也就是多少个字符的含义

with open('a.txt', 'rt')as f:
    data = f.read(3)
    print(data)

with open('b.txt', 'rb') as f:
    data = f.read(2)
    print(data)

之前文件内指针的移动都是由 读/写 操作而被动触发的,若想读取文件某一特定位置的数据,则需要用 f.seek 方法控制文件内指针的移动
0 模式可以在 b 或者 t 模式使用
1/2模式只能在 b 模式下使用

f.seek(指针移动的字节数,模式控制)

0 默认的模式,该模式代表指针的移动的字节数是以文件开头为参照的
1 该模式代表指针移动的字节数是以当前所在的位置为参照的
2 该模式代表指针移动的字节数是以文件末尾为参照的

写入文件

with open('a.txt', 'wt', encoding='UTF-8')as f:
    s = 'abc芜湖'
    f.write(s)
with open('a.txt', 'rt', encoding='UTF-8') as f:
    data = f.read()
    print('文件内容:', data)

文件内容: abc芜湖

0 模式

with open('a.txt', 'rt', encoding='UTF-8') as f:
    f.seek(3,0)
    print(f.tell())
    print(f.read())

3
芜湖


with open('a.txt', 'rt', encoding='UTF-8') as f:
    f.seek(6,0)
    print(f.tell())
    print(f.read())

6
湖

1 模式

with open('a.txt', 'rb') as f:
    f.seek(3,1)
    print(f.tell())
    f.seek(4,1)
    print(f.tell())

3
7

2 模式

with open('a.txt', 'rb') as f:
    f.seek(0, 2)
    print(f.tell())
    f.seek(-3, 2)
    print(f.read().decode('UTF-8'))

9
湖

demo

import time
with open('access.log', 'rb') as f:
    f.seek(0,2)
    while 1:
        line = f.readline()
        if len(line) == 0:
            time.sleep(0.5)
        else:
            print(line.decode('UTF-8'), end='')

四、文件修改

with open('a.txt', 'wt', encoding='UTF-8') as f:
    data = "TimCook USA 185 65 12312312321\nJson USA 163 60 14324324234\nTom USA 175 62 1231243423421"
    f.write(data)
with open('a.txt', 'rt', encoding='UTF-8') as f:
    res = f.read()
    print('修改之前:\n', res)
with open('a.txt', 'r+t', encoding='UTF-8') as f:
    f.seek(7)
    f.write('<Apple>')
with open('a.txt', 'r', encoding='UTF-8') as f:
    res = f.read()
    print('修改之后:\n', res)

修改之前: 
TimCook USA 185 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
修改之后: 
TimCook<Apple>5 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421

磁盘空间是无法修改的,磁盘中的数据更新都是用新数据覆盖旧数据
内存中的数据是可以修改的
修改文件的大致思路是将文件内容读取到内存,然后在内存中修改完成,再讲内存中的内容覆盖回磁盘

方式一

将文件内容一次性全部读取到内存,然后在内存中修改完成之后再覆写会源文件

优点:在文件修改过程中同一份数据只有一份

缺点:会过多占用内存

with open('a.txt', 'wt', encoding='UTF-8') as f:
    data = "TimCook USA 185 65 12312312321\nJson USA 163 60 14324324234\nTom USA 175 62 1231243423421"
    f.write(data)

with open('a.txt', 'rt', encoding='UTF-8') as f:
    res = f.read()
    print('修改之前:\n',res)

with open('a.txt', 'r+t', encoding='UTF-8') as f:
    f.write(res.replace('USA', 'CHINA'))

with open('a.txt', 'r', encoding='UTF-8') as f:
    res = f.read()
    print('修改之后:\n',res)


修改之前:
 TimCook USA 185 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
修改之后:
 TimCook CHINA 185 65 12312312321
Json CHINA 163 60 14324324234
Tom CHINA 175 62 1231243423421

方式二

以读的方式打开源文件,以写的方式打开一个临时文件,一行行读取源文件内容,修改完之后写入临时文件,删除源文件,将临时文件重命名为源文件名

优点:不会占用过多的内存

缺点:在文件修改过程中同一份数据保存了两份

import os
with open('a.txt', 'wt', encoding='UTF-8') as f:
    data = "TimCook USA 185 65 12312312321\nJson USA 163 60 14324324234\nTom USA 175 62 1231243423421"
    f.write(data)
with open('a.txt', 'rt', encoding='UTF-8') as f:
    res = f.read()
    print('修改之前:\n',res)
with open('a.txt', 'r') as src_f, open('.a.txt.swap', 'w') as dst_f:
    for line in src_f:
        dst_f.write(line.replace('USA', 'China'))
os.remove('a.txt')
os.rename('.a.txt.swap', 'a.txt')
with open('a.txt', 'r') as f:
    res = f.read()
    print('修改之后:\n',res)


修改之前:
 TimCook USA 185 65 12312312321
Json USA 163 60 14324324234
Tom USA 175 62 1231243423421
修改之后:
 TimCook China 185 65 12312312321
Json China 163 60 14324324234
Tom China 175 62 1231243423421

posted @ 2022-10-13 21:57  大胡萝卜没有须  阅读(78)  评论(0编辑  收藏  举报