Python学习-对文件的操作

记录下python中文件的操作,文件操作主要三步:打开文件、操作文件句柄、关闭文件句柄。以下为打开一个文件的实例,使用open方法打开,f为文件句柄。

f=open(r'长沙4S店联系方式.txt',encoding='utf-8',mode='r')

其中打开文件使用open函数,其为内置函数,底层调用的是操作系统的接口。第一个参数为路径,路径名前加一个r,可以规避路径里转义的问题。

encoding可以默认不写,编码默认是操作系统的默认编码,windows默认是gbk,linux和macOS默认是utf-8。

mode为打开的方式,有读(r)、写(w)、追加(a)、读写(rw)。

文件读

文件读可以整个文件读、按照字符读取、按行读取、多行读取、for循环读取,操作文件内容如下。

messi
ronald
herry

(1)全部读取

f1=open(r'文件的读.txt',encoding='utf-8')

#  1 read全部读出来 整个文件读取
content=f1.read()
print(content,type(content))
f1.close()

(2)按照字符读取

# 2 read(n) 按照字符读取
content=f1.read(5) # 'messi',读取了5个字符
print(content)
f1.close()

(3)按行读取,多行读取

# 3 按照行来读
print(f1.readline()) # messi
print(f1.readline()) # ronald

# 4 readlines() 整个文件读取,返回列表
print(f1.readlines()) #['messi\n', 'ronald\n', 'herry']

(4)for循环读取

当文件非常大时,这种读取方式显然是更好的,每次读取只会读取一行的数据到内存,打印完后把内存中这行删除掉。

# 5 for循环读取
for line in f1:
    print(line)

f1.close()

# 结果
messi

ronald

herry

读取一个文件时mode可以选r、rb、r+、r+b,一般使用r和rb,具体如下表。

mode 说明
r 只读方式打开文件,操作的一般是文本文件,指针默认会放在文件开头
rb 二级制格式打开一个文件用于只读,操作的一般是非文本的文件,如音频、视频、图片,指针默认会放在文件开头
r+ 打开文件用于读写,指针默认在文件开头
r+b 以二进制格式打开一个文件用于读写,指针在文件开头

如使用rb打开图片内容如下无实际意义,可再写入到文件用于复制图片。

f2=open('美女.jpg',mode='rb')
content=f2.read()
print(content)
f2.close()

# 读取后以字节形式展示
\xfe/z\xa8\xdb\xa9:\x94\xc5\xb1\xdb\xf5\xa65\xb7?\x85^\x08E1\xd3\x00\xff\x00JN\xe0U\x10\xe2\x9a\xf1e\xea\xc3.\x07\xf3\xa6\xca\xb8\xff\x00\xf5\xd4u\x0b\x15\xde=\xd4\xdf\'&\xa6\x1cSJ\xed>\xa6\xa8\x08[\xe4\x1f\xca\x800)\xce\xfcc\xd6\x9b\x8c\x8a\x05`\xf2\xc9\x1e\xbcPF3N^\x7f\x955\x8e\xda

文件写

文件的写操作,直接使用write方法到文件。

f=open('文件的写.txt',encoding='utf-8',mode='w')
f.write('我是最帅的')
f.close()

写一个文件时mode可以选可以选择w、wb、w+、w+b,具体如下表。

mode 说明
w 打开一个文件只用于写入,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容
wb 二级制格式打开一个文件用于只写入,操作的一般是非文本的文件,如音频、视频、图片,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容
w+ 打开文件用于读写,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容
w+b 以二进制格式打开一个文件用于读写,如果文件不存在就创建新文件写入内容,如果文件存在就清空原来的内容,写入新的内容

下例为使用rb模式打开图片内容再写入到文件用于复制。

# 先读取内容
f1=open('美女.jpg',mode='rb')
content=f1.read()
f1.close()
# 写入读取的内容实现复制
f2=open('美女copy.jpg',mode='wb')
f2.write(content)
f2.close()

文件追加

文件的追加,也是用write方法,模式更换为a即可,其会在文件末尾追加内容,不会像写模式的直接覆盖。

# 文件的追加,没有文件就创建一个文件追加
f=open('文件的追加.txt',encoding='utf-8',mode='a')
f.write('\n我最帅')
f.close()

# 有文件,就在原来的基础上,追加内容
f=open('文件的追加.txt',encoding='utf-8',mode='a')
f.write('\n我也最坏')
f.close()

# 执行完后文件内容
我最帅
我也最坏

追加一个文件时mode可以选可以选择a、ab、a+、a+b,具体如下表。

mode 说明
a 打开一个文件只用于追加,如果文件不存在就创建新文件写入内容,如果文件存在,指针放到文件结尾写入新的内容到已有内容之后
ab 二级制格式打开一个文件用于追加,如果文件不存在就创建新文件写入内容,如果文件存在,指针放到文件结尾写入新的内容到已有内容之后
a+ 打开文件用于读写,如果文件不存在就创建新文件用于读和追加,如果文件存在,指针放到文件结尾。
a+b 以二进制格式打开一个文件用于追加,如果文件不存在就创建新文件用于读和追加,如果文件存在,指针放到文件结尾。

打开文件的其他操作

使用操作文件内容如下。

messi

(1)先读后写

使用r+模式,刚开始指针默认在文件开头,执行read方法后指针移到文件末尾,再次写入内容会追加到文件末尾

# 先读后写
f1=open(r'文件的读.txt',encoding='utf-8',mode='r+')
content=f1.read()
print(content) # messi
print('目标光标位置:',f1.tell()) # 目标光标位置: 5,utf-8的编码格式,中文一个字符3个字节,英文一个字符1个字节
f1.write('\n先读后写的内容')
f1.close()

执行完后,文件内容如下,中文内容写到文件末尾。

messi
先读后写的内容

(2)先写后读

使用操作文件内容如下。

我为我儿子学编程哈哈

使用r+模式,刚开始指针默认在文件开头,执行write方法后指针移到写入内容的末尾。

# 先写后读
f1=open('文件的读.txt',encoding='utf-8',mode='r+')
f1.write('先读后写的内容')
content=f1.read() 
print(content) # 程哈哈
f1.close()

执行完后,文件内容如下,光标从文件开头写完内容,最后光标会移动到写入部分文件的末尾,原文件内容还有部分未被覆盖,再执行read方法读取的就是'程哈哈'。

先读后写的内容程哈哈

以上两种情况,考虑指针移动的位置,就好理解。

tell seek flush

操作文件内容如下。

abc123中

(1)tell() :获取光标字节位置

代码如下,光标位置刚开始在文件开头,tell执行后为0,读取内容后光标移动到文件末尾,再次tell执行后为9,utf-8的编码格式下,'abc123'占用6个字节,'中'占用3个字节。

f1=open('文件操作的其他功能.txt',encoding='utf-8',mode='r')
print(f1.tell()) # 0
print(f1.read()) # abc123中
print(f1.tell()) # 9 

(2)seek(): 调整光标的字节位置

代码如下,光标移动6位后,走过了'abc123',再次读取后内容为'中'。

f1=open('文件操作的其他功能.txt',encoding='utf-8',mode='r')
f1.seek(6)
print(f1.read()) # 中

方法tell和seek可以用在文件断点续传。

(3)flush() :强制刷新,用来把文件从内存缓冲区中强制刷新到硬盘中,同时清空缓冲区。一般情况下,文件句柄关闭后会自动刷新到硬盘,但有时需要在关闭前刷新到硬盘,这时就可以使用 flush() 方法。

f1=open('文件的写.txt',encoding='utf-8',mode='w')
f1.write('hello')
f1.write('python')
f1.flush()
print(f1.tell()) # hellopython
f1.close()

with open打开文件

有点类似SQL里的with as,代码如下,这种不需要手动关闭文件句柄。

# 不用手动关闭文件句柄
with open('文件的读.txt',encoding='utf-8') as f1:
    print(f1.read())

# 一个with,可以操作多个open
with open('文件的读.txt',encoding='utf-8',mode='r') as f1,open('文件的写.txt',encoding='utf-8',mode='w') as f2:
    print(f1.read())
    f2.write('打开文件的另外一种方式')

文件的修改

操作文件内容如下。

clyang是最帅的
当然,clyang也是最坏的
你问clyang是谁,那就是我了

python中没有文件修改的方法,需要使用取巧的方式实现,步骤如下。

  1. 以读的模式打开源文件
  2. 以写的模式创建一个新文件
  3. 将源文件的内容读取出来并修改成新内容,写入新文件
  4. 将源文件删除
  5. 将新文件重命名为原文件
# low版本的修改,没有考虑内存溢出
import os
with open('文件的修改.txt', encoding='utf-8', mode='r') as f1, \
        open('文件的修改.txt_bak', encoding='utf-8', mode='w') as f2:
    # 读取文件内容
    content = f1.read()
    # 修改
    new_content=content.replace('clyang','超哥')
    # 写入新文件
    f2.write(new_content)
# 删除旧文件
os.remove('文件的修改.txt')
# 重命名新文件
os.rename('文件的修改.txt_bak','文件的修改.txt')


# 进阶版,考虑内存溢出
import os
with open('文件的修改.txt', encoding='utf-8', mode='r') as f1, \
        open('文件的修改.txt_bak', encoding='utf-8', mode='w') as f2:
    for line in f1:
        # 读一行,修改一行
        new_line=line.replace('超哥','clyang')
        # 修改一行,写一行
        f2.write(new_line)
# 删除旧文件
os.remove('文件的修改.txt')
# 重命名新文件
os.rename('文件的修改.txt_bak','文件的修改.txt')

执行后文件内容中'clyang'都被替换。

超哥是最帅的
当然,超哥也是最坏的
你问超哥是谁,那就是我了

文件操作练习

使用文件操作,结合前面学习的知识点,练习一下。

练习1 追加模式修改内容并读取

在如下内容上,以a+模式添加"卧梅又闻花",然后从最开始将原内容读取出来。

葫芦娃,葫芦娃,
一根藤上七个瓜,
风吹雨打,都不怕,
啦啦啦啦。

上代码,追加内容后,需要使用seek调整光标的字节位置到开头后读取内容。

seek(0):光标移动到最前面;seek(0,2):光标移动到最后面

with open('葫芦娃',encoding='utf-8',mode='a+') as f1:
    f1.write('\n卧梅又闻花')
    # 光标移动到最前面
    f1.seek(0)
    # 光标移动到最后面,2就是文件尾
    # f1.seek(0,2)
    content=f1.read()
    # 退回5个字符,读取原文件内容
    print(content[:-5])

练习2 读取商品文件生成列表

文件price.txt中的内容,每一行内容分别为商品名 价钱 个数,中间空格隔开。需要通过代码,构建成列表数据类型,元素为字典类型: [{'name':'apple','price':10,'amount':3},{'name':'benz','price':200000,'amount':1},...],并计算总价。

apple 10 3
benz 200000 1
mac 8888 2
acer 4500 3
chicken 10 5

上代码,除了读取文件部分为新增知识,其他都是以前的知识点,下面是常规的方法,首先想到就是这种思路。

li=[]
with open('price.txt',encoding='utf-8',mode='r') as f1:
    for line in f1:
        data=line.split(' ')
        name=data[0]
        price=int(data[1])
        amount=int(data[2].strip())
        # 添加到字典
        # 以下两张方法都可以
        # dic={}
        # dic['name']=name
        # dic['price']=price
        # dic['amount']=amount
        dic={'name':name,'price':price,'amount':amount}
        # 添加到列表
        li.append(dic)
print(li)

# 统计总价
sum=0
for item in li:
    sum+=item.get('price')*item.get('amount')
print('商品总价为{}'.format(sum))

生成字典并append到列表前,字典的生成有诀窍,如果文件内容新增一列或多列,按照上面代码写法,需要把字典后面的字段进行补充,会增加代码行数。按照下面的写法将更加灵活,文件增加列数,只需要增加在li_name列表中添加key即可,其他代码均不需要修改。

li=[]
li_name=['name','price','amount'] # 如果原文件增加一列,只需要在这里添加key就可以,其他不用修改
with open('price.txt',encoding='utf-8',mode='r') as f1:
    for line in f1:
        # key和value一一对应的数据都准备好了
        item_list=line.strip().split()
        dic = {}
        # 循环,生成字典
        for index in range(len(li_name)):
            dic[li_name[index]]=item_list[index]
        li.append(dic)
print(li)

修改后执行效果。

[{'name': 'apple', 'price': '10', 'amount': '3'}, {'name': 'benz', 'price': '200000', 'amount': '1'}, {'name': 'mac', 'price': '8888', 'amount': '2'}, {'name': 'acer', 'price': '4500', 'amount': '3'}, {'name': 'chicken', 'price': '10', 'amount': '5'}]

PS:以上,理解不一定正确,学习就是一个不断认识和纠错的过程,如果有误还请批评指正。

参考博文:

(1)https://www.cnblogs.com/on2road/p/12044503.html r+和w+

(2)https://www.cnblogs.com/chen55555/p/10185488.html

(3)https://www.cnblogs.com/wushuaishuai/p/8508506.html

posted @ 2021-07-31 23:15  斐波那切  阅读(161)  评论(0编辑  收藏  举报