IO 流

I/O 流(Input/Output Stream) 是程序中用于处理输入和输出的机制。在 Python 中,I/O 流主要用于读写文件、处理网络数据、与用户交互等操作。


1. I/O 流的基本概念

I/O 流是数据在程序和外部设备(如文件、网络、终端等)之间流动的通道。Python 的 I/O 流分为两种:

  1. 文本流(Text Stream):处理文本数据,默认使用 Unicode 编码。
  2. 二进制流(Binary Stream):处理二进制数据,如图片、音频、视频等。

2. 文件 I/O

文件 I/O 是最常见的 I/O 操作,Python 提供了内置的 open() 函数来操作文件。

2.1 打开文件

使用 open() 函数打开文件,语法如下:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
  • file:文件路径(字符串或字节)。
  • mode:打开文件的模式(见下表)。
  • encoding:文本文件的编码方式(如 'utf-8')。
  • 返回值:返回一个文件对象。
模式 描述
r 字符模式打开文件。只读。文件指针在文件开头。文件不存在会报错
rb 同上,字节模式
r+ 字符模式打开文件。读写。文件指针在文件开头。文件不存在会报错
rb+ 同上,字节模式
w 字符模式打开文件。只写。文件指针在文件开头。
如果文件不存在就新建,如果存在就清空内容准备写入
按这种模式一打开文件,内容就会被清空
wb 同上,字节模式
w+ 字符模式打开文件。读写。文件指针在文件开头。
如果文件不存在就新建,如果存在就清空内容准备写入
按这种模式一打开文件,内容就会被清空,所以只能读取到本次写入的内容
wb+ 同上,字节模式
a 字符模式打开文件。只写(末尾写入)。文件指针在文件末尾。
文件不存在会新建,存在就打开,不会清空内容。文件指针在文件末尾
ab 同上,按字节模式
a+ 字符模式打开文件。读写(末尾写入)。文件指针在文件末尾。
文件不存在会新建,存在就打开,不会清空内容。文件指针在文件末尾
ab+ 同上,字节模式

示例

# 打开一个文本文件(只读模式)
file = open('example.txt', 'r', encoding='utf-8')

# 打开一个文本文件(写入模式,只要文件一打开,内容就被清空了)
file = open('test.txt', 'w', encoding='utf-8')

2.2 读取文件

文件对象提供了多种读取数据的方法:

方法 描述
read(size) 读取指定大小的数据(字节或字符),默认读取全部内容。
readline() 读取一行数据。
readlines() 读取所有行,返回一个列表。
for line in file: 逐行读取文件(推荐方式)。

示例

# 读取整个文件,不带参数就读全部,带参数表示读取指定数量的字符或字节(看什么模式打开的文件)
content = file.read()
print(content)

# 逐行读取文件
for line in file:
    print(line)

# 读取一行
line = file.readline()
print(line)

# 读取所有行
lines = file.readlines()
print(lines)

2.3 写入文件

文件对象提供了多种写入数据的方法:

方法 描述
write(string) 写入字符串数据。
writelines(lines) 写入多行数据(列表或迭代器)。

示例

# 写入字符串
file.write("Hello, World!\n")

# 写入多行数据
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
file.writelines(lines)

2.4 关闭文件

使用 close() 方法关闭文件,释放资源。

file.close()

使用 with 语句(推荐)

with 语句可以自动管理文件的打开和关闭,避免资源泄漏。

with open('example.txt', 'r', encoding='utf-8') as file:
    content = file.read()
    print(content)
# 文件会在 with 块结束后自动关闭

3. 文件指针

文件读到哪指针就移动到哪,写入一样的,写到哪指针就在哪。如果是字符模式,就是第几个字符的位置

文件指针的基本概念

  • 文件指针:文件指针是一个标记,表示当前文件读写的位置。
  • 默认行为
    • 打开文件时,文件指针的位置取决于打开模式:
      • 'r''r+':文件指针位于文件开头。
      • 'w''w+':文件指针位于文件开头(但文件内容会被清空)。
      • 'a''a+':文件指针位于文件末尾。
  • 移动文件指针:通过 seek() 函数可以移动文件指针。
  • 获取文件指针位置:通过 tell() 函数可以获取当前文件指针的位置。

seek() 函数

seek() 函数用于移动文件指针到指定位置

file.seek(offset, whence)
  • offset:移动的字节数(偏移量)。
    • 正数:向文件末尾方向移动。
    • 负数:向文件开头方向移动。
  • whence:参考位置,可选参数,默认为 0
    • 0:从文件开头计算偏移量。
    • 1:从当前文件指针位置计算偏移量。
    • 2:从文件末尾计算偏移量。

tell() 函数

tell() 函数用于获取当前文件指针的位置。

file.tell()

文件指针的注意事项

  1. 文本模式和二进制模式的区别
    • 文本模式 下,seek()tell() 的行为可能会受到编码的影响(如 utf-8 编码中,某些字符可能占用多个字节)。
    • 二进制模式 下,seek()tell() 的行为是精确的,以字节为单位。
  2. 文件指针的移动范围
    • 文件指针不能移动到文件开头之前或文件末尾之后。
    • 如果 seek() 的偏移量超出文件范围,会抛出 ValueError
  3. 写入操作的影响
    • 写入操作会从当前文件指针位置开始,并移动文件指针到写入内容的末尾

示例

# 假设文件 example.txt 内容为:Hello, World!

with open('text.text', 'r+', encoding='utf-8') as file:
    # 读取前 5 个字符
    print(file.read(5))  # 输出: Hello

    # 获取当前文件指针位置
    print("当前指针位置:", file.tell())  # 输出: 当前指针位置: 5

    # 将文件指针移动到文件开头
    file.seek(0)
    print("移动后指针位置:", file.tell())  # 输出: 移动后指针位置: 0

    # 读取文件内容
    print(file.read())  # 输出: Hello, World!

    # 将文件指针移动到文件末尾
    file.seek(0, 2)
    print("移动后指针位置:", file.tell())  # 输出: 移动后指针位置: 13

    # 指针移动到第5个字符(也就是 o 后面,Hello| )
    file.seek(5, 0)
    print(f"11当前指针位置: {file.tell()}")  # 输出:11当前指针位置: 5

    print(file.read())  # 输出 , World!

4. 中间插入

示例1

假设文件 example.txt 的内容如下:

Line 1
Line 2
Line 3
Line 4

我们希望在 Line 2Line 3 之间插入一行 New Line

# 文件路径
file_path = 'example.txt'

# 要插入的文本
new_text = "New Line\n"

# 打开文件并读取所有内容
with open(file_path, 'r', encoding='utf-8') as file:
    lines = file.readlines()  # 读取所有行,返回一个列表

# 找到插入位置(在 Line 2 和 Line 3 之间)
insert_index = 2  # 在第 2 行之后插入(索引从 0 开始)

# 在内存中插入新内容
lines.insert(insert_index, new_text)

# 将修改后的内容写回文件
with open(file_path, 'w', encoding='utf-8') as file:
    file.writelines(lines)  # 将列表写入文件

# 输出修改后的文件内容
with open(file_path, 'r', encoding='utf-8') as file:
    print("修改后的文件内容:")
    print(file.read())

修改后的文件内容:

Line 1
Line 2
New Line
Line 3
Line 4

示例2

假设文件 example.txt 的内容如下:

Line 1
Line 2
Line 3
Line 4

我们希望在 Line 2Line 3 之间插入一行 New Line

# 文件路径
file_path = 'example.txt'

# 要插入的文本
new_text = "New Line\n"

# 打开文件(使用 'r+' 模式支持读写)
with open(file_path, 'r+', encoding='utf-8') as file:
    # 找到插入点(在 Line 2 和 Line 3 之间)
    # 假设每行长度固定,或者通过逐行读取找到插入点
    file.seek(0)  # 将文件指针移动到开头
    lines = file.readlines()  # 读取所有行
    insert_index = 2  # 在第 2 行之后插入(索引从 0 开始)

    # 计算插入点的字节位置
    file.seek(0)  # 重新将文件指针移动到开头
    insert_position = 0
    for i, line in enumerate(lines):
        if i == insert_index:
            break
        insert_position += len(line.encode('utf-8'))  # 计算字节位置

    # 读取插入点之后的内容
    file.seek(insert_position)  # 移动文件指针到插入点
    remaining_content = file.read()  # 读取插入点之后的内容

    # 写入新内容和剩余内容
    file.seek(insert_position)  # 移动文件指针到插入点
    file.write(new_text)  # 写入新内容
    file.write(remaining_content)  # 写入剩余内容

# 输出修改后的文件内容
with open(file_path, 'r', encoding='utf-8') as file:
    print("修改后的文件内容:")
    print(file.read())

修改后的文件内容:

Line 1
Line 2
New Line
Line 3
Line 4
posted @ 2025-03-09 13:05  CyrusHuang  阅读(42)  评论(0)    收藏  举报