为什么要学 Python 档案处理?

Python 档案处理是程式设计中一个非常重要的环节,无论你是想:

  • 储存资料: 将程式运算的结果、使用者输入的资料或是从网路抓取的资料储存起来,方便日后分析或使用。
  • 读取资料: 从档案中读取资料进行进一步的处理,例如资料分析、机器学习等。
  • 建立应用程式: 许多应用程式都需要与档案系统互动,例如文字编辑器、图片浏览器、资料库管理系统等。

Python 档案处理的优势

  • 资料持久化: 将程式运行的结果储存到档案中,即使程式结束运行,资料也不会丢失。
  • 资料共享: 可以将资料储存到档案中,方便与他人共享或在不同程式之间传递。
  • 自动化任务: 可以写 Python 程式自动化处理大量档案,提高工作效率。
  • 建立更复杂的应用程式: 档案处理是许多复杂应用程式的基础。
  • 语法简单: Python 的档案处理语法非常直观,容易学习。
  • 功能强大: Python 提供了丰富的函式库,可以处理各种格式的档案。
  • 跨平台: Python 程式可以在不同的作业系统上运行,档案处理功能也具有良好的跨平台性。

常见的档案处理应用场景

  • 资料分析: 从 CSV、Excel 等档案中读取资料,进行统计分析、资料视觉化等。
  • 网页爬虫: 将网页内容下载并储存到本地档案中。
  • 资料库操作: 将资料储存到资料库中,或从资料库中读取资料。
  • 配置档案: 读取配置档案,设定程式的运行参数。
  • 日誌记录: 将程式的运行状态记录到档案中,方便排错。

Python 档案处理方法:

功能
解释
范例
开启档案open("filename.txt", "mode") 开启档案 filename.txt。常见模式有:r 读取、w 覆写、a 追加、x 创建新档案、b 二进位模式。 file = open("filename.txt", "r")
读取整个档案 .read() 读取档案所有内容,返回为字串。 words = file.read()
读取指定数量的字元 .read(n) 读取指定字元数量 n,返回为字串。 word = file.read(6)
读取单行 .readline() 读取下一行内容,返回为字串。 first_line = file.readline()
读取所有行 .readlines() 读取所有行并返回列表,每行作为列表的一个元素。佔记忆体 lines = file.readlines()
写入档案 .write(str) 将字串 str 写入档案(覆盖模式)。 file.write("Hello, world!\\n")
写入多行 .writelines(seq) 将 seq 序列中的每个元素作为一行写入档案,适用于列表或元组 lines = ["Line 1\\n", "Line 2\\n"] file.writelines(lines)
使用 print() 写入 print(data, file=file) 使用 print() 函数将 data 写入到指定的档案 file。 data = "Hello, world!" print(data, file=file)
使用 with 自动关闭with open("filename.txt", "mode") as file 使用 with 开启档案,程式执行完毕后会自动关闭档案。 with open("filename.txt", "w") as file: file.write("Hello, world!")
with 和 writelines() with open("my_file.txt", "w") as file file.writelines(lines) 利用 with 配合 writelines() 一次写入多行,避免忘记关闭档案。
print() 导向档案 print(data, file=f) 将 print() 函数的输出导向指定的档案 f。

开启档案open()

基本语法

file = open("filename.txt", "mode")
file.close()

filename.txt: 要开启的档案名称相对路径。mode: 开启模式,常见的有:r: 读取 (预设)w: 写入 (覆写)a: 追加 (在档案末尾追加)x: 创建新档案 (如果档案已存在则报错)

进阶使用与 with 一起使用 开启档案

什么是 with 陈述式?with 陈述式是一种上下文管理器,它让程式码更简洁,并且能自动释放资源。为什么要用 with 陈述式?在处理档案、资料库连接等资源时,为了避免忘记关闭档案导致的资源洩露,使用 with 陈述式能确保资源在使用完毕后被自动正确关闭档案,即使发生异常。with 陈述式的语法

with open(expression,"mode") as variable:
# 在这个区块中,可以使用 variable 来访问资源

  • expression:通常是一个函式呼叫,返回一个上下文管理器物件。
  • variable:一个变数,用来表示上下文管理器所管理的资源。

with open("my_file.txt", "a" as file:
file.write("This is a new line.\\n")

as file 中的 file 是自定义的as file 中的 file 并不是 Python 的关键字,而是一个变量名称。你可以将它换成任何你喜欢的变量名称

读取档案 "r"

一次读取所有内容.read():

假设我有一份my_file.txt 里面内容为:

I love python
I love Club

with open("my_file.txt","r") as file:
words = file.read()
print(words)

#输出
I love python
I love Club

读取指定数量的位元组.read(n):

with open("my_file.txt","r") as file:
word = file.read(6)
print(word)
file.close()
#输出 I love

单行读取.readline()

with open("my_file.txt","r") as file:
first_line = file.readline()
second_line = file.readline()
print(second_line,first_line,sep=\'\\n\')

#输出
I love Club
I love python

逐行读取.readlines()

它会将文件中的每一行读取为一个元素,并将这些元素存储在一个列表中。

with open("my_file.txt","r") as file:
a = file.readlines()
print(a)

#输出
[\'I love python\\n\',
\'I love Club\']

# 遍历每一行
with open("my_file.txt","r") as file:
for line in file.readlines():
print(line)

#输出
I love python

I love Club

编码 (encoding)

什么是编码(encoding)?

编码是将文字转换成电脑可以理解的二进位数字的过程。不同的编码方式使用不同的对应关系,例如 ASCII、UTF-8、Big5 等。

为什么要了解编码?

在读取或开启文件时,python会根据你电脑的os预设encoding来呈现,但如果跟其他人写入文件的encoding不同,就 有可能会看到乱码 。所以在处理文字档案时,必须指定正确的编码方式,才能正确地读取和写入资料。

常见的编码:

  • UTF-8: 最常用,一种可变长度的 Unicode 转码格式,几乎可以表示世界上所有的文字。
  • ASCII: 主要用于显示现代英文的字元。
  • Big5/cp950: 常用于繁体中文的编码。

结合范例

with open(\'my_file.txt\', \'r\', encoding=\'utf-8\') as f:
for line in f:
print(line, end=\'\')

写入档案

常见写入档案的模式

\'w\': 写入模式,如果档案存在则会覆盖原有档案内容。如果档案不存在,则会创建新档案。\'a\': 附加模式,用于在档案末尾追加内容。如果档案不存在,则会创建新档案。\'x\': 排他性创建模式,如果档案已经存在则会报错。\'b\': 二进位模式,用于读写二进位资料。\'t\': 文字模式(预设),用于读写文字资料。

使用\'w\' 模式写入档案的步骤

先打开档案写入,再读取(分开操作,无法同时写入和读取)原因: 在同一个 with 语句中,使用 \'w\' 模式开启档案后,档案就处于写入状态。如果你想在写入之后立即读取,需要重新开启档案,并使用 \'r\' 模式。

# 以写入模式开启一个名为 my_file.txt 的档案
with open(\'my_file.txt\', \'w\', encoding=\'utf-8\') as f:
#写入档案
file.write("Hello, world!\\n") # 写入一行文字
#再读取
with open(\'my_file.txt\', \'r\', encoding=\'utf-8\') as f:
for line in f:
print(line, end=\'\')

这段程式码做了以下事情:

  • 开启档案: 使用 with open() 开启名为 my_file.txt 的档案,以读取模式开启,并指定编码为 UTF-8。
  • 逐行读取: 使用 for 迴圈逐行读取档案内容,并将每一行印出。
  • 自动关闭: 离开 with 区块时,档案会自动关闭。

使用\'a\' 模式来追加写入并读取(同一个档案)

# 写入档案
with open(\'my_file.txt\', \'a\', encoding=\'utf-8\') as f:
f.write("Hello, world!\\n")

# 读取档案
with open(\'my_file.txt\', \'r\', encoding=\'utf-8\') as f:
for line in f:
print(line, end=\'\')

使用\'x\' 模式

\'x\' 模式 的主要用途是 创建一个新档案,如果档案已经存在,就会报错。因此,它并不能直接用于追加写入和读取同一个档案。

with open(\'my_file.txt\', \'x\') as f:
f.write("第一次写入\\n")
# 追加写入
with open(\'my_file.txt\', \'a\') as f:
f.write("追加内容\\n")
# 读取
with open(\'my_file.txt\', \'r\') as f:
for line in f:
print(line, end=\'\')

其他写入档案的方式 .writelines(seq)

在 Python 中,当我们想要一次性将一个序列(例如列表或元组)中的多个字符串写入到一个档案中时,,并且在每个字符串的末尾自动添加一个换行符。.writelines(seq) 方法是一个非常方便的选择。

with open("my_file.txt", "w", encoding=\'utf-8\') as file:
lines = ["第一行\\n", "第二行\\n", "第三行\\n", "test\\n"]
file.writelines(lines)

其他写入档案的方式 print(data,file=f)

在 Python 中,print() 函数通常用来将资料输出到终端(也就是我们平常看到的命令列)。然而,透过指定 file 参数,我们可以将输出导向到一个档案中,而不是显示在萤幕上。-data: 你想要写入档案的资料,可以是字符串、数字、或是更复杂的资料结构。-file: 要写入的档案对象。这个对象通常是透过 open() 函数取得的。

with open(\'my_file.txt\', \'w\') as file:
data = "Hello, world!\\n"
print(data, file=file)

with open(\'movieList.txt\', \'w\', encoding=\'utf-8\')as f:
movies = [\'movie1\', \'movie2\', \'movie3\']
print(movies, file=f)

option

Python 的 seek() 方法:精準控制档案读写位置

seek() 函数的用途

seek() 函数在 Python 中主要用于在档案中移动读写位置。想像一个档案就像是一本书,而 seek() 就如同将书籤移动到书的任意页面。透过这个函数,我们可以精準地控制从档案的哪个位置开始读取或写入资料。

seek() 的参数

offset: 偏移量,表示要移动的位元组数。可以是正数(向后移动)、负数(向前移动)或 0(无移动)。whence: 可选参数,表示偏移量的参考位置。0 (os.SEEK_SET):档案的起始位置1 (os.SEEK_CUR):当前的文件位置2 (os.SEEK_END):档案的结尾位置

常见的使用情境

随机存取档案:

  • 从任意位置开始读取: 将 offset 设为要开始读取的位元组数,whence 设为 0。
  • 在特定位置插入资料: 将 offset 设为插入位置,whence 设为 0,然后使用 write() 方法写入资料。

处理大型档案:

  • 分段读取: 对于过大的档案,一次性读取可能会导致记忆体不足。可以使用 seek() 分段读取,每次只读取一小部分。
  • 跳过无用资料: 如果档案中包含大量无用的资料,可以使用 seek() 跳过这些部分,直接定位到需要的资料。
  • 修改档案内容:
    • 替换特定内容: 将文件指针移动到要替换的内容的起始位置,然后使用 write() 方法写入新的内容。
    • 插入新内容: 将文件指针移动到插入位置,然后使用 write() 方法写入新的内容。

with open(\'my_file.txt\', \'r+\') as f:
# 移动到档案末尾
f.seek(0, 2)
# 在末尾追加一行
f.write(\'\\nThis is a new line.\')

# 移动到档案开头
f.seek(0)
# 读取前10个位元组
data = f.read(10)
print(data)

注意事项二进位模式 vs. 文字模式: 在二进位模式下,seek() 操作的是位元组,而在文字模式下,seek() 操作的是字元。不同系统的换行符: 在不同作业系统中,换行符的表示方式不同。Windows 使用 \\r\\n,而 Unix/Linux 使用 \\n。文件指针: seek() 操作会改变文件指针的位置,后续的读写操作都会从新的位置开始。档案类型: 不是所有的档案都支持随机存取,例如压缩档案或资料库档案。结语seek() 函数为我们提供了对档案进行精细控制的能力,在处理各种档案操作时都非常有用。通过熟练掌握 seek() 的用法,我们可以更灵活地处理档案资料。

常见的应用场景:

编辑器: 在编辑器中,seek() 可以用于实现光标的移动和内容的插入、删除。资料库: 资料库系统中,seek() 可以用于定位到特定的记录。网路通讯: 在网路通讯中,seek() 可以用于处理接收到的资料包。