文件的高级应用

文件的高级应用

一、可读、可写(不经常用到,了解即可)

  • r+t:可读、可写 r+
  • w+t:可写、可读 w+
  • a+t:可追加、可读 a+
# r+  r+w
with open(r'text.txt',mode='r+',encoding='utf-8') as f:
    print(f.readable())
    print(f.writable())
    f.write('嘿嘿嘿')
    
True
True    
# w+t w+t
with open(r'text.txt',mode='w+',encoding='utf-8') as f:
    print(f.readable())
    print(f.writable())
    
True
True    
# a+t a+
with open(r'text.txt','a+',encoding='utf-8') as f:
    print(f.readable())
    print(f.writable())
True
True    

二、文件内光标移动

假设我们需要在文件内容中间的某一行增加内容,如果使用基础的r\w\a模式实现是非常困难的,因此我们需要对文件内的指针进行移动。

硬盘上从来没有修改一说,硬盘上只有覆盖,即新内容覆盖老内容。

在rt模式下,read内的数字,表示的是字符的个数,除此之外,数字表示的都是字节

with open(r'text.txt','r',encoding='utf-8') as f:
    print(f.read(5))  # 读取了5个字节

今天是一个    

在rb模式下,read内的数字,表示的的是字节的个数。

with open(r'text.txt','rb') as f:
    res = f.read(12)
    print(res)  # 读取的是12个字节   3个字节表示一个中文字符 
    print(res.decode('utf-8'))  # 将二进制数据解码成utf-8二进制

b'\xe4\xbb\x8a\xe5\xa4\xa9\xe6\x98\xaf\xe4\xb8\x80'
今天是一    

1.f.seek(offset,whence) 光标移动

  • offset:相对偏移量 光标移动的位数
  • whence:
    • 0:参照文件的开头,t和b都可以使用
    • 1:参照光标所在的当前位置,只能b使用
    • 2:参照文件的末尾,只能在b模式中使用
# whence:0
with open(r'text.txt','rt',encoding='utf-8') as f:
    print(f.read(1))  # 今
    f.seek(6,0)  # 从将光标从文件开头移动6bytes
    print(f.read(1))  # 是 读取一个字符
    # f.seek(4,0)  # 将光标从开头移动了4个字节,由于汉字是由3个字节表示一个字符,所以会报错
    f.seek(0,0)  # 光标从开头移动0个字节,还在开头,
    print(f.read(1))  # 读取一个字符
    f.seek(6,0)  # 
    print(f.read())
# whence:1
with open(r'text.txt','rb') as f:
    print(f.read(3).decode('utf-8'))  # 读取3个字节并用utf-8解码,(今)
    f.seek(3,1)  # 将指针从当前位置移动3个字节,
    print(f.read(1))  # 读取一个字节
    f.seek(6,0)  # 将指针从文件开头移动6个字节,即2个字符
    print(f.read(3))  # 读取3个字节
    f.seek(4,0)  # 将指针从文件开头移动4个字节,
    print(f.read(2))  # 读取2个字节
    
# whence:3
with open(r'text.txt','rb') as f:
    print(f.read())  # 读取文件内所有的字节
    f.seek(-9,2)  # 指针从末尾向前移动9个字节
    print(f.read().decode('utf-8'))  # 读取字节并解码成utf-8二进制
    
with open(r'text.txt','r+',encoding='utf-8') as f:
    f.seek(3,0)
    f.write('时')  # 在第一个字符后面,写入一个字符,会将原来的字符覆盖掉

今时是一个好日子
今天是一个好日子
今天是一个好日子
今天是一个好日子
今天是一个好日子
今天是一个好日子
今天是一个好日子
今天是一个好日子    

2.f.tell(int):查看光标移动了多少位

with open(r'text.txt','r+',encoding='utf-8') as f:
    f.seek(18,0)
    print(f.tell())
18    

3.f.truncate(int):截断文件

接收字节的长度(保留0~6字节数,后面的全部删除)

truncate(n)是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate()要在r+或a或a+等模式下测试效果。它的参照物永远是文件头。并且teuncate()不加参数,相当于清空文件。

with open(r'text.txt','a',encoding='utf-8') as f:
    f.truncate(12)  # (12)接收的字节长度
    # 保留0-12字节数,后面的全部删除(截断)

三、写日志、检测文件内容

# 写日志.py
import time
res = time.strftime('%Y-%m-%d %X')

with open(r'text.txt','a',encoding='utf-8') as f:
    f.write(f'{res} egon给jason发了一亿的工资\n')

# 检测文件内容
with open(r'text.txt','rb') as f:
    f.seek(0,2)  # 将光标移动到末尾
    while True:
        res = f.readline()  # 每次读取光标后面的一行

        # print(f.tell())  # 光标移动的字节数

        if res:  # 存在(即检测到新添加的内容)
            print(f'新增的内容:{res.decode("utf-8")}')  # 打印
        # else:
        #     print('暂无其他人操作该文件')

四、修改内容

由于硬盘上从来没有修改一说,硬盘上只有覆盖,即新内容覆盖老内容。那我们如何修改文件呢?

方法一:

  • 现将数据由硬盘读到内存(读取文件)
  • 在内存中完成修改(字符串的替换)
  • 再覆盖原来的内容(写文件)
with open(r'text.txt','r',encoding='utf-8') as fr:
    data = fr.read()
    print(data)
    # print(type(data))

with open(r'text.txt','w',encoding='utf-8') as fw:
    res = data.replace('egon','nick')
    fw.write(res)

  • 优点:任意时间硬盘上只有一个文件,不会占用过多硬盘空间
  • 缺点:当文件过大的情况下,可能会造成内存溢出。

方法二:

  • 创建一个新文件
  • 循环读取老文件内容到内存进行修改,将修改好的内容写到新文件中
  • 将老文件删除,将新文件的名字改为老文件。
import os
with open(r'text.txt','r',encoding='utf-8') as fr,\
open(r'text.swap','a',encoding='utf-8') as fw:
    for line in fr:  # 将文件内容一行行读取
        new_line = line.replace('nick','egon')  # 对文件的每一行替换
        fw.write(new_line)  # 写入新文件

os.remove('text.txt')  # 移除文件
os.rename('text.swap','text.txt')  # 重命名文件

posted @ 2019-07-09 22:32  最后的别离  阅读(176)  评论(0编辑  收藏  举报