666999666999 发表于 2025-8-16 16:49:10

文件对象方法write和writelines写入字符数量的问题

分别用write、writelines这两种方法向写入相同的字符串,为什么最后字符数量不一样
代码如下
a = open("fish.txt","w+")
f = open("FishC.txt","w+")
a.write("I love FishC.\nI love my wife.")
f.writelines(["I love FishC.\n","I love my wife."])
a.tell()
29
f.tell()
30
但是每次从头用read()方法读取它俩数据的时候,不论read里面的参数设置成多少,他们读取的数据都一样
求大佬解惑{:10_282:}

FishC 发表于 2025-8-16 16:53:56

您的代码中 `writelines()` 没有参数,这会导致错误(实际代码中应有参数)。推测您可能这样调用:

# write 方式
a.write("I love FishC.\nI love my wife.")# 直接写入整个字符串

# writelines 方式(假设传入列表)
lines = ["I love FishC.\n", "I love my wife."]
f.writelines(lines)


### 问题原因:
1. 换行符转换(文本模式特性):
   - 在 w+(文本模式)下,写入 \n 时:
   - Windows 系统自动转换为 \r\n(2字节)
   - Linux/Mac 保持 \n(1字节)
   - 您的 tell() 结果差异源于此转换。

2. 字符串长度计算:
   - 原字符串总长度:29 字符(含1个 \n)
   
   "I love FishC.\n"   # 14字符(\n占1位)
   "I love my wife."    # 15字符
   总计:14 + 15 = 29
   

3. 关键差异:
   - write() 写入 整个字符串,系统按需转换换行符。
   - writelines() 写入 字符串列表,每个元素独立处理换行符。

### 为什么 `tell()` 结果不同?
假设在 Windows 系统:
- `a.write(...)` 后:
- 实际写入内容:I love FishC.\r\nI love my wife.
- 字节数:28普通字符 + \r\n(2字节) + 15字符 = 30字节
- 但 tell() 返回 29(逻辑位置,非实际物理偏移)。

- `f.writelines(lines)` 后:
- 实际写入内容:
   
    "I love FishC.\r\n"   # 15字节(\n被转\r\n)
    "I love my wife."       # 15字节
    总计:15 + 15 = 30字节
   
- tell() 返回 30。

### 为什么 `read()` 读取内容相同?
- 文本模式下的 read() 会自动将 \r\n 转换回 \n。
- 无论实际存储是 \n 还是 \r\n,读回程序后都会变成 \n。

### 验证方法:
用二进制模式读取实际存储内容:

# 检查 a 文件(write写入)
with open("fish.txt", "rb") as file:
    print(file.read())# 输出 b'I love FishC.\r\nI love my wife.'(Windows)

# 检查 f 文件(writelines写入)
with open("FishC.txt", "rb") as file:
    print(file.read())# 输出 b'I love FishC.\r\nI love my wife.'(Windows)


### 总结:
| 方法          | 系统       | 实际存储字节数 | `tell()` 返回值 | 读取后内容          |
|---------------|------------|----------------|-----------------|---------------------|
| `write()`   | Windows    | 30 字节      | 29            | 与原始字符串一致    |
| `writelines()`| Windows    | 30 字节      | 30            | 与原始字符串一致    |
| 两者          | Linux/Mac| 29 字节      | 29            | 与原始字符串一致    |

结论:
这是由文本模式的换行符转换导致的物理存储差异,但读取时会自动还原为统一的 \n,因此内容显示一致。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

不二如是 发表于 2025-8-17 19:35:06

在 Python 中,write() 和 writelines() 都用于将数据写入文件,但它们在处理换行符(\n)的方式上有所不同,这导致了你在读取文件时看到的字符数量差异。

write() 方法

write() 方法将整个字符串作为一个整体写入文件,不会自动添加换行符:

a = open("fish.txt", "w+")
a.write("I love FishC.\nI love my wife.")
字符串 "I love FishC.\nI love my wife." 被写入文件。换行符 \n 是字符串的一部分,因此文件中包含了换行。


writelines() 方法

writelines() 方法接受一个字符串列表,并将每个字符串依次写入文件。

它不会自动添加换行符,除非你在字符串中明确包含:

f = open("FishC.txt", "w+")
f.writelines(["I love FishC.\n", "I love my wife."])
两个字符串被写入文件,每个字符串末尾都有换行符 \n。


字符数量差异的原因

鱼油提到在调用 a.tell() 时返回 29,而 f.tell() 返回 30。

因为 write() 方法在写入字符串时,可能会在字符串末尾添加额外的换行符,导致字符数增加。

当你使用 read() 方法读取文件时,Python 会根据操作系统的默认设置处理换行符。

在 Windows 系统上,换行符通常是 \r\n,而在类 Unix 系统上是 \n。Python 会自动处理这些差异。

with open("fish.txt", "r") as file:
    content = file.read()
    print(repr(content))
这将输出文件的内容,包括换行符。

结论:


[*]write():将整个字符串写入文件,不会自动添加换行符。
[*]writelines():将字符串列表写入文件,不会自动添加换行符,除非字符串中包含。
[*]字符数量差异:可能是由于 write() 方法在写入时添加了额外的换行符。
[*]读取文件:Python 会根据操作系统的默认设置处理换行符。


为了确保一致的换行行为,建议在使用 write() 或 writelines() 时,显式地在字符串中包含换行符。

薰衣草的花语 发表于 2025-8-18 07:07:40

学习

尉尉的可乐 发表于 2025-8-18 08:20:50

两个不一样

smallwh 发表于 2025-8-18 09:45:53

是不是 python 版本特性?3.8.5 不能复现。

666999666999 发表于 2025-8-18 14:55:53

smallwh 发表于 2025-8-18 09:45
是不是 python 版本特性?3.8.5 不能复现。

我又试了一下跟你这一样了,奇怪,之前是不一样的,遇到bug了{:10_291:}

sfqxx 发表于 2025-8-19 15:18:56

学习
页: [1]
查看完整版本: 文件对象方法write和writelines写入字符数量的问题