Python文件操作

在 Python 中,文件操作是非常常见的任务。Python 提供了内置的函数来处理文件的读写操作。

文件的类型

  1. 文本文件:包含可读的字符(如 .txt.csv)。一般使用 UTF-8 编码,可以使用文本编辑器查看;
  2. 二进制文件:包含非文本数据(如图像、音频、视频文件,后缀如 .jpg.png.mp3)。以原始字节格式存储。需要使用专用软件查看;

文件操作的过程

  1. 打开文件;

  2. 读写文件;

    • 读文件:将文件内容读入内存;

    • 写文件:将内存内容写入文件;

  3. 关闭文件;

操作方法

打开文件

使用 open() 函数打开文件

open 函数负责打开文件,并且返回文件对象

  1. 第一个参数是文件名(文件名区分大小写),第二个参数是打开方式;
  2. 如果文件存在返回文件操作对象;
  3. 如果文件不存在抛出异常
f = open("文件名", "访问方式")

文件路径

绝对路径:

从根路径开始描述文件的位置,例如:F:\技术文件\课件-笔记\课件修订\Python\01.Python基础语法

具有唯一性,不会出错,不管写在哪里都可以准确的找到文件的位置

相对路径:

相对当前位置进行文件定位,容易出错,需要对路径比较熟悉

以不同模式打开

访问方式 说明
r 只读方式打开文件。文件的指针将会放在文件的开头,这是默认模式。如果文件不存在,抛出异常
w 只写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件
a 追加方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入
r+ 读写方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常
w+ 读写方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件
a+ 读写方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入

以bytes类型操作的读写,写读,写读模式

r+b 读写【可读,可写】
w+b 写读【可写,可读】
a+b 写读【可写,可读】

对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)

注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

文件编码

f=open(...)是由操作系统打开文件,那么如果我们没有为open指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。

f=open('example.txt','r',encoding='utf-8')

读取文件

  • read(size):读取指定大小的内容,如果没有指定,读取全部内容。
  • readline():读取一行。
  • readlines():读取所有行并返回一个列表。

示例:

file = open('example.txt', 'r')

content = file.read()          # 读取全部内容
line = file.readline()      # 读取一行
lines = file.readlines()      # 读取所有行

print(content)
print('-----------')
print(line)
print('-----------')
print(lines)

# 思考?
# 为什么后面两个print读取不到东西呢?

文件指针 seek

有时候我们想要改变文件指针(光标)的位置,就需要用到seek方法来操作指针

语法:

file.seek(offset, whence)
  • offset:要移动的字节数。

  • whence

    (可选):指定偏移量的基准位置。可以取以下值:

    • 0:从文件开头开始计算(默认值)。
    • 1:从当前位置开始计算。
    • 2:从文件末尾开始计算

示例:

file = open('example.txt', 'r')

content = file.read()          # 读取全部内容
file.seek(0)                # 把光标移到到文件的开头
line = file.readline()      # 读取一行
file.seek(0)                # 再次把光标移动到文件的开头
lines = file.readlines()      # 读取所有行

print(content)
print('-----------')
print(line)
print('-----------')
print(lines)

按行读取文件内容

  • read方法默认会把文件的所有内容一次性读取到内存
  • readline方法可以一次读取一行内容
# 方式一、通过循环按行读取文件所有内容
file1 = open("example.txt")
i = 1
while True:
    text1 = file1.readline().strip()
    if text1:
        print("这是第%s行内容" % i)
        i += 1
        print(text1)
    else:
        break

file1.close()

file2 = open("example.txt")

# 通过for遍历按行读取文件所有内容
for i in file2.readlines():
    print(i.strip())

file2.close()

写入内容

可以对文件对象调用write方法实现写入内容

语法:

file.write()

示例:日记记录

# 日记程序
# 以追加模式打开日记文件
file = open('diary.txt', 'a',encoding='utf-8')

# 获取用户输入的日记内容
content = input("请输入今天的日记:")

# 将日记内容写入文件
file.write(content + "\n")
print("日记已保存!")

# 关闭文件
file.close()

关闭文件

语法:

file.close()

使用 close() 方法关闭文件,释放系统资源,防止文件被一直占用

with结构

使用 with 语句可以自动管理文件的打开和关闭,避免忘记关闭文件的情况。

with open('example.txt', 'r') as file:        # 获取file文件对象
    content = file.read()

案例:简单的备份程序

将一个文本文件的内容复制到另一个文件,用于简单的备份。

# 简单备份小程序
source = 'a.txt'
destination = 'b.txt'

with open(source, 'r',encoding='utf-8') as src:
    content = src.read()

with open(destination, 'w',encoding='utf-8') as dest:
    dest.write(content)

print(f"备份成功!'{source}' 的内容已复制到 '{destination}'")

其他文件操作

除了上述讲到的常用操作之外,还有很多其他的操作。这里我们列出在这,就不一一带着大家去看了。用到的时候可以回头来查一下就行

class CustomFile:
    def __init__(self, *args, **kwargs):
        """初始化文件对象."""
        pass

    @staticmethod
    def __new__(*args, **kwargs):
        """创建并返回一个新的对象."""
        pass

    def close(self, *args, **kwargs):
        """关闭文件."""
        pass

    def fileno(self, *args, **kwargs):
        """返回文件描述符."""
        pass

    def flush(self, *args, **kwargs):
        """刷新文件内部缓冲区."""
        pass

    def isatty(self, *args, **kwargs):
        """判断文件是否是一个终端设备."""
        pass

    def read(self, *args, **kwargs):
        """读取指定字节的数据."""
        pass

    def readable(self, *args, **kwargs):
        """检查文件是否可读."""
        pass

    def readline(self, *args, **kwargs):
        """仅读取一行数据."""
        pass

    def seek(self, *args, **kwargs):
        """移动文件指针到指定位置."""
        pass

    def seekable(self, *args, **kwargs):
        """检查指针是否可操作."""
        pass

    def tell(self, *args, **kwargs):
        """获取当前指针位置."""
        pass

    def truncate(self, *args, **kwargs):
        """截断文件,仅保留指定之前的数据."""
        pass

    def writable(self, *args, **kwargs):
        """检查文件是否可写."""
        pass

    def write(self, *args, **kwargs):
        """写入内容到文件."""
        pass

    def __next__(self, *args, **kwargs):
        """实现迭代器的 next() 方法."""
        pass

    def __repr__(self, *args, **kwargs):
        """返回文件对象的字符串表示."""
        pass

    def __getstate__(self, *args, **kwargs):
        """自定义对象的序列化状态."""
        pass

解释

  1. __init__: 初始化文件对象的方法。通常在这里设置文件的基本属性。
  2. __new__: 静态方法,用于创建新的对象实例。
  3. close: 关闭文件,释放系统资源。
  4. fileno: 返回文件描述符,通常用于与底层操作系统交互。
  5. flush: 刷新文件的内部缓冲区,将未写入的数据写入文件。
  6. isatty: 判断文件是否是一个终端设备(tty),用于检查文件是否连接到一个用户界面。
  7. read: 读取指定字节的数据,可以用来读取文件内容。
  8. readable: 检查文件对象是否可读。
  9. readline: 读取文件中的一行数据,常用于逐行读取文件内容。
  10. seek: 移动文件指针到指定位置,允许在文件中随机访问。
  11. seekable: 检查文件指针是否可操作,确定文件是否支持随机访问。
  12. tell: 返回当前文件指针的位置。
  13. truncate: 截断文件,只保留指定位置之前的数据。
  14. writable: 检查文件对象是否可写。
  15. write: 向文件写入内容。
  16. __next__: 实现迭代器的 next() 方法,用于支持迭代访问文件的内容。
  17. __repr__: 返回文件对象的字符串表示,通常用于调试。
  18. __getstate__: 自定义对象的序列化状态,用于存储和恢复对象的状态。

案例练习

案例一 文件修改

文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:

方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

import os

with open('a.txt') as read_f,open('a.txt.new','w') as write_f:
    data = read_f.read()
    data = data.replace('Hello','nihao')

    write_f.write(data)

os.remove('a.txt')
os.rename('a.txt.new','a.txt')

方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件

import os

with open('a.txt') as read_f,open('a.txt.new','w') as write_f:
    for line in read_f:
        line = line.replace('nihao','Hello')
        write_f.write(line)

os.remove('a.txt')
os.rename('a.txt.new','a.txt')

案例二 商品信息管理与总价计算

背景

在日常的商业管理中,商品的管理和销售记录是非常重要的。我们需要一种方式来处理商品信息,包括商品名称、价格和数量。通过这些信息,我们可以计算出总价,帮助商家了解销售情况。

目标

本案例旨在通过 Python 读取存储在文本文件中的商品信息,并将其转换为易于操作的数据结构。具体目标包括:

  1. 从文件 a.txt 中读取每一行的商品信息。
  2. 将读取的信息构建为包含字典的列表,每个字典表示一个商品,包含名称、价格和数量。
  3. 计算所有商品的总价,并输出结果。

文件内容示例

a.txt 文件的内容如下:

apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3

每行代表一个商品,格式为:商品名称 价格 数量

代码示例

# 初始化商品列表
products = []

# 读取文件并构建商品列表
with open('a.txt', 'r', encoding='utf-8') as file:
    for line in file:
        # 去除行首尾空白并分割
        parts = line.strip().split()
        if len(parts) == 3:  # 确保有三个部分
            product = {
                'name': parts[0],
                'price': int(parts[1]),  # 转换为整数
                'amount': int(parts[2])   # 转换为整数
            }
            products.append(product)

# 输出商品列表
print("商品列表", products)

total_price = 0
# 计算总价
for i in products:
    total_price += i['price'] * i['amount']

# 输出总价
print("总价:", total_price)

# Output:
[{'name': 'apple', 'price': 10, 'amount': 3}, {'name': 'tesla', 'price': 100000, 'amount': 1}, {'name': 'mac', 'price': 3000, 'amount': 2}, {'name': 'lenovo', 'price': 30000, 'amount': 3}, {'name': 'chicken', 'price': 10, 'amount': 3}]
总价: 196060

案例三 基于文件的账户验证

将用户信息存放在文件user.txt中,并且格式如下

张三|123456

代码示例:

db = {}
with open("sql.txt","r", encoding="utf-8") as f:
    data = f.readlines()
    print(data)
    for i in data:
        ret = i.strip().split("|")
        # ret = ["张三", "123"]
        print(ret)
        db[ret[0]] = ret[1]
        # db["张三"] = "123"
        print(db)

while True:
    username = input("请输入用户名:")

    if username in db:
        password = input("请输入密码:")
        if password ==db[username]:
            print("登录成功")
        else:
            print("密码错误登录失败")
    else:
        print("用户名不存在")

课后作业

1. 完成上述几个案例
2. 扩展案例三 基于文件的账户验证。为其增加注册功能并且让整个代码更加合理
3. 尝试一下实现密码错误3次封号的功能
学前沿IT,到英格科技!本文发布时间: 2024-09-20 21:52:34

results matching ""

    No results matching ""