文件内指针的移动单位一般是Bytes,但也有特殊情况:t模式下的read(n)操作,n代表文件指针移动的单位字符个数。
# 读出二进制解码得到的字符串:hello你好
# 硬盘:                  0101010101101010101011010101010
# 只有t模式下read(n),这个n代表的字符个数——————特殊情况
# UTF-8标准下,一个英文字符是一个字节Byte,一个中文字符代表三个字节,3Bytes。
with open(‘a.txt‘,mode=‘rt‘,encoding=‘utf-8‘) as f:
    data=f.read(6)
    print(f.tell())  # 8 = 5+3  
    print(data)  # hello你
了解:硬盘容量的本之就是能够存多少二进制数bit
# 字节换算
8bit=>1Byte
1024Byte = 1KB
1024KB=1MB
1024MB=1GB
1024GB=1TB
# 硬盘换算
1GB=1024*1024*8
b模式打开文本文件、字符的解码、utf-8
with open("a.txt",mode="rb") as f:
    data = f.read(8)
    print(type(data))  # <class ‘bytes‘>
    print(len(data))  # 8
    print(data.decode("utf-8"))  # hello你
b模式打开文本文件、字符的解码、gbk
with open("a.txt",mode="rb") as f:
    data = f.read(7)
    print(type(data))  # <class ‘bytes‘>
    print(len(data))  # 7
    print(data.decode("gbk"))  # hello鍝  由于文本文件是使用utf-8编码的,所以使用gbk用来解码无法解除正确的字符,utf-8模式下,一个中文字符对应三个字节,而gbk模式对应2个字节,所以出现错误字符。
截断,是一种写操作
with open(r"C:\Users\ccf\PycharmProjects\S15\day010\a.txt", mode="r+t", encoding="utf-8") as f:
    f.truncate(7)  # hello?  hello哈 有8个字节,第七个字节截断会出现乱码
f.seek(x,y)
x代表的是移动的字节个数
y代表的模式:
1) 0:代表参照物是文件开头,可以在t模式和b模块下使用
2) 1:代表参照物是当前位置,只能在b模式下用
3) 2:代表参照物是文件末尾,,只能在b模式下用
with open(‘d.txt‘, mode=‘rt‘, encoding=‘utf-8‘) as f:  # 哈hello
    f.read(3)        # 3个字符
    print(f.tell())  # 5个字节
    f.seek(3, 0)     # 0模式,3字节
    print(f.tell())  # 指针从开头移动3个字节
with open(‘d.txt‘, mode=‘rb‘) as f:  # 哈hello
    f.read(1)       # 1字节
    print(f.tell()) # 1字节
    f.seek(2,1)     # 2字节,从一字节位置往后
    print(f.tell()) # 3字节
with open(‘d.txt‘, mode=‘rb‘) as f:
    # f.seek(3333, 2)
    # print(f.tell()) # 14+3333=3347
    # f.seek(-3, 2)
    # print(f.tell())
    f.seek(0, 2)  # 快速将指针移动到文件末尾
    print(f.tell())
案例:日志监控
tail -f access.log
import time
with open(r"/day10/代码/access.log", mode="rb") as f:
    f.seek(0, 2)  # 快速将指针移动到文件末尾
    while True:
        line = f.readline()    #  每次读取一行数据
        if len(line) == 0:
            time.sleep(0.1)    #  停顿时间0.1s
        else:
            print(line.decode(‘utf-8‘),end=‘‘)
# 文件a.txt内容如下
张一蛋     山东    179    49    12344234523
李二蛋     河北    163    57    13913453521
王全蛋     山西    153    62    18651433422
# 执行操作
with open(‘a.txt‘,mode=‘r+t‘,encoding=‘utf-8‘) as f:
    f.seek(9)
    f.write(‘<妇女主任>‘)
# 文件修改后的内容如下
张一蛋<妇女主任> 179    49    12344234523
李二蛋     河北    163    57    13913453521
王全蛋     山西    153    62    18651433422
# 强调:
# 1、硬盘空间是无法修改的,硬盘中数据的更新都是用新内容覆盖旧内容
# 2、内存中的数据是可以修改的
# 实现思路:
1) 将文件内容发一次性全部读入内存,
2) 然后在内存中修改完毕
3) 最后再覆盖写回原文件
# 优点: 不费硬盘,在文件修改过程中同一份数据只有一份
# 缺点: 费内存,会过多地占用内存
with open(‘db.txt‘,mode=‘rt‘,encoding=‘utf-8‘) as f:
    data=f.read()
with open(‘db.txt‘,mode=‘wt‘,encoding=‘utf-8‘) as f:
    f.write(data.replace(‘K‘,‘S‘))
# 实现思路:
1) 以读的方式打开原文件,以写的方式打开一个临时文件,
2) 一行行读取原文件内容,修改
3) 修改完后写入临时文件...,删掉原文件,将临时文件重命名原文件名
# 优点: 不费内存,不会占用过多的内存
# 缺点: 费硬盘,在文件修改过程中同一份数据存了两份
import os
with open(‘db.txt‘,mode=‘rt‘,encoding=‘utf-8‘) as read_f,        open(‘.db.txt.swap‘,mode=‘wt‘,encoding=‘utf-8‘) as wrife_f:
    for line in read_f:
        wrife_f.write(line.replace(‘S‘,‘K‘))
os.remove(‘db.txt‘)
os.rename(‘.db.txt.swap‘,‘db.txt‘)
原文:https://www.cnblogs.com/huluhuluwa/p/13109874.html