Files
python-flask/project4/01.Python文件操作.md
2025-09-11 16:13:52 +08:00

474 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Python文件操作
在 Python 中文件操作是非常常见的任务。Python 提供了内置的函数来处理文件的读写操作。
## 文件的类型
1. **文本文件**:包含可读的字符(如 `.txt``.csv`)。一般使用 UTF-8 编码,可以使用文本编辑器查看;
2. **二进制文件**:包含非文本数据(如图像、音频、视频文件,后缀如 `.jpg``.png``.mp3`)。以原始字节格式存储。需要使用专用软件查看;
## 文件操作的过程
1. 打开文件;
2. 读写文件;
- 读文件:将文件内容读入内存;
- 写文件:将内存内容写入文件;
3. 关闭文件;
# 操作方法
## 打开文件
使用 `open()` 函数打开文件
`open` 函数负责打开文件,并且返回文件对象
1. 第一个参数是文件名(文件名区分大小写),第二个参数是打开方式;
2. 如果文件存在返回文件操作对象;
3. 如果文件不存在抛出异常
```python
f = open("文件名", "访问方式")
```
### 文件路径
#### **绝对路径:**
从根路径开始描述文件的位置,例如:`F:\技术文件\课件-笔记\课件修订\Python\01.Python基础语法`
具有唯一性,不会出错,不管写在哪里都可以准确的找到文件的位置
#### **相对路径:**
相对当前位置进行文件定位,容易出错,需要对路径比较熟悉
### 以不同模式打开
| 访问方式 | 说明 |
| -------- | ------------------------------------------------------------ |
| r | 以**只读**方式打开文件。文件的指针将会放在文件的开头,这是**默认模式**。如果文件不存在,抛出异常 |
| w | 以**只写**方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
| a | 以**追加**方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
| r+ | 以**读写**方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,抛出异常 |
| w+ | 以**读写**方式打开文件。如果文件存在会被覆盖。如果文件不存在,创建新文件 |
| a+ | 以**读写**方式打开文件。如果该文件已存在,文件指针将会放在文件的结尾。如果文件不存在,创建新文件进行写入 |
以bytes类型操作的读写写读写读模式
| r+b | 读写【可读,可写】 |
| :--- | :----------------- |
| w+b | 写读【可写,可读】 |
| a+b | 写读【可写,可读】 |
对于非文本文件我们只能使用b模式"b"表示以字节的方式操作而所有文件也都是以字节的形式存储的使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式
<font color=red>以b方式打开时读取到的内容是字节类型写入时也需要提供字节类型不能指定编码</font>
### 文件编码
f=open(...)是由操作系统打开文件那么如果我们没有为open指定编码那么打开文件的默认编码很明显是操作系统说了算了操作系统会用自己的默认编码去打开文件在windows下是gbk在linux下是utf-8。
```python
f=open('example.txt','r',encoding='utf-8')
```
## 读取文件
- **`read(size)`**:读取指定大小的内容,如果没有指定,读取全部内容。
- **`readline()`**:读取一行。
- **`readlines()`**:读取所有行并返回一个列表。
示例:
```python
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方法来操作指针
**语法:**
```python
file.seek(offset, whence)
```
- **`offset`**:要移动的字节数。
- `whence`
(可选):指定偏移量的基准位置。可以取以下值:
- `0`:从文件开头开始计算(默认值)。
- `1`:从当前位置开始计算。
- `2`:从文件末尾开始计算
**示例:**
```python
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方法可以一次读取一行内容
```python
# 方式一、通过循环按行读取文件所有内容
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方法实现写入内容
**语法:**
```python
file.write()
```
**示例:日记记录**
```python
# 日记程序
# 以追加模式打开日记文件
file = open('diary.txt', 'a',encoding='utf-8')
# 获取用户输入的日记内容
content = input("请输入今天的日记:")
# 将日记内容写入文件
file.write(content + "\n")
print("日记已保存!")
# 关闭文件
file.close()
```
## 关闭文件
**语法:**
```python
file.close()
```
使用 `close()` 方法关闭文件,释放系统资源,防止文件被一直占用
## with结构
使用 `with` 语句可以自动管理文件的打开和关闭,避免忘记关闭文件的情况。
```python
with open('example.txt', 'r') as file: # 获取file文件对象
content = file.read()
```
**案例:简单的备份程序**
将一个文本文件的内容复制到另一个文件,用于简单的备份。
```python
# 简单备份小程序
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}'")
```
## 其他文件操作
除了上述讲到的常用操作之外,还有很多其他的操作。这里我们列出在这,就不一一带着大家去看了。用到的时候可以回头来查一下就行
```python
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__`**: 自定义对象的序列化状态,用于存储和恢复对象的状态。
# 案例练习
## 案例一 文件修改
文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
方式一将硬盘存放的该文件的内容全部加载到内存在内存中是可以修改的修改完毕后再由内存覆盖到硬盘wordvimnodpad++等编辑器)
```python
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')
```
方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
```python
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
```
每行代表一个商品,格式为:`商品名称 价格 数量`
#### 代码示例
```python
# 初始化商品列表
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
```
**代码示例:**
```python
db = {}
with open("user.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("用户名不存在")
```