08 文件操作

本节主要内容:

1. 初识文件操作

2.只读(r, rb)

3.只写(w, wb)

4.追加(a, ab)

5.r+读写

6.w+写读

7.a+写读(追加写读)

8.其他操作方法(seek(n)光标移动到n位置, tell()获取光标的位置, truncate()截断文件)

9.文件的修改以及另一种打开文件句柄的方式

主要内容:
⼀一. 初识⽂文件操作
使⽤用python来读写⽂文件是非常简单的操作. 我们使⽤用open()函数来打开⼀一个⽂文件, 获取到⽂文
件句句柄. 然后通过⽂文件句句柄就可以进⾏行行各种各样的操作了了. 根据打开⽅方式的不同能够执⾏行行的操
作也会有相应的差异.
打开⽂文件的⽅方式: r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b 默认使⽤用的是r(只读)模式

read(), read(n)

1. read() 将⽂文件中的内容全部读取出来. 弊端: 占内存. 如果⽂文件过⼤大.容易易导致内存崩溃

2.read(n) 读取n个字符. 需要注意的是. 如果再次读取. 那么会在当前位置继续去读⽽而不
是从头读, 如果使⽤用的是rb模式. 则读取出来的是n个字节

f = open("胡辣汤", mode="r", encoding="utf-8")
content = f.read(3)  # read(n) 读取n个字符
content = f.read() # 一次性全都读取出来读取文件中的内容

readline(), readlines()

readline() ⼀一次读取⼀一⾏行行数据, 注意: readline()结尾, 注意每次读取出来的数据都会有⼀一
个 所以呢. 需要我们使⽤用strip()⽅方法来去掉 或者空格

readlines()将每⼀一⾏行行形成⼀一个元素, 放到⼀一个列列表中. 将所有的内容都读取出来. 所以
也是. 容易易出现内存崩溃的问题.不推荐使⽤用

line = f.readline() # 读取一行数据
print(line.strip()) # strip()去掉空白。空格, 	 


lst = f.readlines() # 一次性全都读取出来, 返回的是列表
print(lst)
路径的问题
两种:
1. 绝对路径(当文件路径是固定的时候)
从磁盘根目录找文件。 windows下用的就是c,d,e,f, linux: userinxxxx
2. 相对路径(用的多)
相对路径相对于当前程序所在的文件夹
../ 表示上一层文件夹

 	 转义字符。 有固定的含义的。 推荐用r
f = open(r"E:哈哈 啦啦啦.txt", mode="r", encoding="utf-8")
print(f.read())

realine 转换成for循环
循环读取. 这种⽅方式是组好的. 每次读取⼀一⾏行行内容.不会产⽣生内存溢出的问题.
#一次读取一行
while 1:
    line = f.readline()
    print(line)

#  文件句柄是一个可迭代对象
f = open("胡辣汤", mode="r", encoding="utf-8")
for line in f: # 读取文件中的内容。 一行一行的读取。 每次读取的内容交给前面的变量
    print(line.strip())

注意: 读取完的⽂文件句句柄⼀一定要关闭 f.close()

write('str') writelines('str')

写的时候注意. 如果没有⽂文件. 则会创建⽂文件, 如果⽂文件存在. 则将原件中原来的内容删除, 再写入新内容

obj1 = open('E:PythonL\11-8\filetest.txt','r')
obj1 = open('filetest.txt','w+')
obj1.write('I heard the echo, from the valleys and the heart
Open to the lonely soul of sickle harvesting
')
obj1.writelines([
                 'Repeat outrightly, but also repeat the well-being of
',
                 'Eventually swaying in the desert oasis'
                 ]

wb模式下. 可以不指定打开⽂文件的编码. 但是在写⽂文件的时候必须将字符串串转化成utf-8的
bytes数据

f = open("⼩小娃娃", mode="wb")
f.write("⾦金金⽑毛狮王".encode("utf-8"))
f.flush()
f.close()

文本文件的复制

# 文本文件的复制
f1 = open(r"c:日记本.txt", mode="r", encoding="utf-8")
f2 = open(r"d:日记本.txt", mode="w", encoding="utf-8")

for line in f1: # 从f1中读取数据
    f2.write(line) # 写入到f2中
f1.close()
f2.close()
b - bytes 读取和写入的是字节 , 用来操作非文本文件(图片, 音频, 视频)
rb, wb, ab
# 把胡一菲从c盘复制到d盘, 单纯的从bytes角度来复制的。 适用于所有文件
f1 = open(r"c:胡一菲.jpg", mode="rb")
f2 = open(r"d:胡二非.jpg", mode="wb")

for line in f1: # 分批量的读取内容
    f2.write(line) # open()出来的结果可以使用read或者write. 根据mode来看

f1.close()
f2.close()

 文件操作 +:

r+ 读写, w+ 写读, a+ 追加写读, r+b, w+b, a+b

+ 扩展

# r+,
#正常的
f = open("person", mode="r+", encoding="utf-8")
content = f.read()
f.write("黄蓉")
print(content)

#错误的示范
f = open("person", mode="r+", encoding="utf-8")
f.write("杨千桦") # 默认如果直接写入的话。 在开头写入。 覆盖开头的内容
content = f.read()
print(content)

# r+
# 深坑请注意: 在r+模式下. 如果读取了了内容. 不论读取内容多少. 光标显⽰示的是多少. 再写入或者操作⽂文件的时候都是在结尾进⾏行行的操作.
#所以如果想做截断操作. 记住了了. 要先挪动光标. 挪动到你想要截断的位置. 然后再进⾏截断关于truncate(n), 如果给出了了n. 则从开头开头进⾏行行截断, 如果不给n, 则从当前位置截断. 后⾯面
#的内容将会被删除
f = open("person", mode="r+", encoding="utf-8") info = f.read(3) f.write("胡辣汤") print(info)

 w+  

先将所有的内容清空. 然后写入. 最后读取. 但是读取的内容是空的, 不常⽤

有⼈人会说. 先读不就好了了么? 错. w+ 模式下, ⼀一开始读取不到数据. 然后写的时候再将原来
的内容清空. 所以, 很少⽤.

f = open("person", mode="w+", encoding="utf-8") # 先清空。 然后再操作
f.write("你好。 我叫肿瘤君")
content = f.read() # 写入东西之后。 光标在末尾。 读取不到内容的
print(content)
f.close()
a+
a+模式下, 不论先读还是后读. 都是读取不到数据的.
# a+, 不论光标在何处 写入的时候都是在末尾
f = open("person", mode="a+", encoding="utf-8")
f.write("我叫李嘉诚") # 默认写在末尾
content = f.read()
print(content)
f.close()

光标

概述

seek() 方法用于移动文件读取指针到指定位置。

语法

seek() 方法语法如下:

fileObject.seek(offset[, whence])

参数

  • offset -- 开始的偏移量,也就是代表需要移动偏移的字节数

  • whence:可选,默认值为 0。给offset参数一个定义,表示要从哪个位置开始偏移;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。 

返回值

该函数没有返回值。

f = open("person", mode="r",encoding='utf-8')
f.read(3) # 读取三个字符
# seek()移动光标
f.seek(3,0)
info = f.read(3) # 读取三个字符
print(info)

如果把seek(3,0)改成seek(3, 1)就会报错

  File "/code/day008 文件操作/07 光标.py", line 5, in <module>
    f.seek(3,1)
io.UnsupportedOperation: can't do nonzero cur-relative seeks

照理说,按照seek()方法的格式file.seek(offset,whence),后面的1代表从当前位置开始算起进行偏移,那又为什么报错呢?
这是因为,在文本文件中,没有使用b模式选项打开的文件,只允许从文件头开始计算相对位置,从文件尾计算时就会引发异常。将  f=open("aaa.txt","r+")  改成

f = open("person","rb")   就可以了
f = open("person", mode="rb")
f.read(9) # 读取三个字符
# seek()移动光标
f.seek(3,0)
info = f.read(9) # 读取三个字符
print(info.decode('utf-8')# 义在于

 tell() 程序返回当前光标的位置

概述

tell() 方法返回文件的当前位置,即文件指针当前位置。

语法

tell() 方法语法如下:

fileObject.tell()

参数

返回值

返回文件的当前位置。

# 生命的意义在于折腾
f = open("person", mode="r",encoding='utf-8')
info = f.read(3)
print(info)
print(f.tell()) # 获取光标位置 9
truncate() 截断文件. 慎用
尽量不要瞎测试, w, w+
f = open(r"C:Program Files (x86)TencentQQBinQQScLauncher.exe", mode="r+", encoding="utf-8")
f.seek(5) # 光标移动到5
f.truncate() # 默认从开头截取到光标位置
# f.truncate(3) # 从头截取到3
f.close()

文件的修改和操作

import os # 导入os模块

import time # 时间模块

# 优点:不用关闭句柄, 自动关闭连接
with open("唐诗", mode="r", encoding="utf-8") as f1,
    open("唐诗_副本", mode="w", encoding="utf-8") as f2:
    for line in f1:
        line = line.replace("善良", "sb")
        f2.write(line)

time.sleep(5)
os.remove("唐诗") # 删除源文件
time.sleep(5)
os.rename("唐诗_副本", "唐诗") # 把副本改名成源文件
'''
编号,名称,价格,数量,仓库,phone
1,榴莲,500,60000,1号仓库,10010
2,苹果,700,70000,2号仓库,10086
1,榴莲,500,60000,1号仓库,155
2,苹果,700,70000,2号仓库,166
'''
f = open("水果.data", mode="r", encoding="utf-8")
titles = f.readline().strip() # 读取第一行 id,name,price,num
t_list = titles.split(",") # 【id,name,price,num】

lst = []
for line in f: # "1,苹果,500,60000"  {id:1,name:liulian, num:xx, price:xxx}
    dic = {}
    ll = line.strip().split(",")
    for i in range(len(t_list)):
        dic[t_list[i]] = ll[i]
    lst.append(dic)
f.close()
print(lst)






原文地址:https://www.cnblogs.com/zero-zero-zero/p/9858494.html