有关linux的文件操作
在 Linux 系统中都说万物皆文件,所以不可避免的需要和文件打交道,我们也会常常对文件进行读和写的操作。例如:
cat /etc/password # 读文件
vim /etc/password # 读写文件
echo test > /tmp/abc.txt # 覆盖写文件
echo text >> /tmp/abc.txt # 追加写文件
而以上内容我们都是对文本文件进行读写,计算机中也存在对二进制文件的读写操作,那用 Python 如何实现呢?
文件的打开方法—open 内建函数
不管是读文件还是写文件,我们第一步都是要将文件打开。
作为打开文件之门的“钥匙”,内建函数 open() 提供了初始化输入/输出(I/O)操作的通用接口,成功打开文件后时候会返回一个文件对象,否则引发一个错误。
基本语法
要以任何方式使用文件——哪怕仅仅是打印其内容,都得先打开打文件,这样才能访问它。
参数介绍
file_name:表示我们要打开文件的路径
mode:以怎样的方式打开文件
文件模式 | 操 作 |
r | 以读方式打开(文件不存在则报错) |
w | 以写方式打开(文件存在则清空,不存在则创建) |
a | 以追加模式打开 |
b | 以二进制模式打开 |
file_object:文件操作对象,我们后续对文件的所有读写操作都需要通过这个对象,而不是直接操作文件中的数据。
文件读操作
要使用文本文件中的信息,首先需要将信息读取到内存中。为此,我们可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。
read 方法 —— 读取文件
- open 函数的第一个参数是要打开的文件名(文件名区分大小写)
- 如果文件 存在,返回 文件操作对象
- 如果文件 不存在,会 抛出异常
- read 方法可以一次性 读入 并 返回 文件的 所有内容
- close 方法负责 关闭文件
- 如果 忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问
- 注意:read 方法执行后,会把 文件指针 移动到 文件的末尾
# 1.打开文件
fr = open("/etc/hosts", mode="r") # r: read
# 2.读取文件
print(fr.read(5)) # 读取前5个字符
print(fr.read(3)) # 接着向后读3个字符
print(fr.read()) # 读取文件剩余的所有内容
print(fr.read()) # 什么都读取不到,因为指针已经在末尾了
# 3.关闭资源
fr.close()
文件指针
- 文件指针 标记 从哪个位置开始读取数据
- 第一次打开 文件时,通常 文件指针会指向文件的开始位置
- 当执行了 read 方法后,文件指针 会移动到 读取内容的末尾
- 默认情况下会移动到 文件末尾
- 重新打开文件时,文件指针 重新指向文件的最 开始位置
图例
思考
- 如果执行了一次 read 方法,读取了所有内容,那么再次调用 read 方法,还能够获得到内容吗?
答案
- 不能,因为第一次读取之后,文件指针移动到了文件末尾,再次调用不会读取到任何的内容
readline 方法 —— 按行读取
- read 方法默认会把文件的 所有内容 一次性读取到内存
- 如果文件太大,对内存的占用会非常严重
- readline 方法可以一次读取一行内容
- 方法执行后,会把 文件指针 移动到下一行,准备再次读取
# 1.打开文件
fr1 = open("/etc/passwd", mode="r") # r:read
# 2.读取文件
print(fr1.readline(), end="") # 读取第一行数据
print(fr1.readline(), end="") # 读取第二行数据
# 3.关闭资源
fr1.close()
案例:读取大文件的正确姿势
# 1.打开文件
fr = open("/etc/passwd", mode="r")
# 2.读取文件
while True: # 死循环
data = fr.readline() # 某一行数据
if len(data) == 0: # 文件读取完毕,终止循环
break
print("data:", data, end="")
# 3.关闭资源
fr.close()
readlines 方法
readlines()方法读取所有(剩余的)行然后把它们作为一个 字符串列表 返回
图例
- 如果需要逐行处理文件,可以结合 for 循环迭代文件
- 迭代文件的方法与处理其他序列类型的数据类似
# 1.打开文件
fr2 = open("/etc/hosts", mode="r")
# 2.读取文件
# 和for连用
# data = fr2.readlines()
# print("data:", data)
# print(data[0]) # 第一行
# print(data[1]) # 第二行
for item in fr2: # 相当于:for item in fr2.readlines():
print(item, end="")
# 3.关闭资源
fr2.close()
文件写操作
write 方法 —— 写文件
- write() 内建方法功能与 read() 和 readline() 相反
- 它把含有 文本数据 或 二进制数据 的内容写入到文件中去
writelines 方法
- 和 readlines() 一样,writelines() 方法是针对 列表 的操作
- 它接受一个 字符串列表 作为参数,将他们写入文件
- 行结束符并不会被自动加入,所以如果需要的话,必须再调用 writelines() 前给每行结尾加上行结束符
# write 方法
# 1.打开文件
fw = open("/opt/dc.txt", mode="w") # w: write
# 2.写文件
fw.write("hello world\n")
fw.write("you are my baby girl~\n")
# 3.关闭资源
fw.close()
案例 3:writelines
# writelines 方法
list01 = ["hello\n", "world\n", "zhangsan\n"]
# 1.打开文件
fw1 = open("/opt/tc.txt", mode="w")
# 2.写文件
fw1.writelines(list01)
# 3.关闭资源
fw1.close()
# hello
# world
# zhangsan
图例:
with 子句
- with语句 是用来简化代码的
- 在将打开文件的操作放在 with 语句中,代码块结束后,文件将自动关闭
- 读写文件的逻辑没有变化,变得只是 写法
案例 4:with
with open('/tmp/passwd', mode="r") as f:
# 文件的读写操作
# ......
练习
# 模拟 cp 操作
# 1. 创建 cp.py 文件
# 2. 将 /usr/bin/ls "拷贝" 到/tmp 目录下
# 3. 不要修改原始文件
方案:
fr = open("/usr/bin/ls", mode="rb") # rb:读取二进制
fw = open("/tmp/myls",mode="wb") # wb:写二进制
while True:
data = fr.read(4096) # 4096字节 = 4k
if len(data) == 0: # 文件读取完毕,终止循环
break
fw.write(data) # 将读到的数据写入文件
fr.close()
fw.close()