010.Python文件指针与文件修改

一、文件指针

(一)文件内指针移动的单位

文件内指针的移动单位一般是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:UsersccfPycharmProjectsS15day010a.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模式下用

1.模式0:代表参照物是文件开头,可以在t模式和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个字节

2.模式1:代表参照物是当前位置,只能在b模式下用

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字节

3.模式2:代表参照物是文件末尾,只能在b模式下用

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