跳转至

📔 Python文件 学习笔记

文件概述

  • 什么是文件?

    • 文件是OS提供给用户/应用程序操作硬盘的一种虚拟的概念/接口
  • 为何使用文件?

    • 用户/应用程序可以通过文件将数据永久保存到硬盘中。即操作文件就是操作硬盘
    • 用户/应用程序直接操作的是文件,对文件的所有操作,都是在向OS发送系统调用,然后再由操作将其转换成具体的硬盘操作。
  • 如何使用文件:open()

    • 控制文件读写内容的模式:t和b
      • 强调:t和b不能单独使用,必须和r/w/a连用。
      • t文本(默认模式):读写都是以str(unicode)为单位进行读写。
        • 文本文件
        • 必须指定encoding='utf-8'
      • b二进制/bytes
1
2
3
# 应用程序发起操作,所以操作系统会允许访问硬盘中的数据文件
f = open(r'./test.txt') # f的值是一种变量,占用的是应用程序的内存空间
print(f)

操作文件:读/写文件

应用程序对文件的读写请求都是在向操作系统发送系统调用,然后操作系统控制硬盘把输入读入内存、或者写入硬盘中。

1
2
3
4
5
6
7
8
f = open(r'./test.txt')
print(f)
res =f.read() # 读取文件

f.close() # 回收操作系统资源
f.read() # 变量f还存在,但是不能进行读操作

del f # 回收应用程序资源,应用程序资源会自动回收

使用with语法 进行上下文管理

# 没有指定encoding参数操作系统会使用自己默认的编码
# Linux和MAC OS系统默认是utf-8
# 在windows中系统默认是gbk
# 文件对象也可以称为文件句柄
# t 模式会将f.read()读出的结果解码出unicode
# with open(r'../test1.txt'b,mode='rt',encoding="utf-8") as f1:
with open(r'../test1.txt'b,mode='rt') as f1,open(r'../test2.txt',mode='rt') as f2: # 等价于 f1 = open(r'../test.txt',mode='rt')
    res = f1.read()
    print(res)
    # with 会自动帮忙执行close
    # f1.close()
    # f2.close()

r 模式

# r 默认的操作模式:只读模式,当文件不存在时就会直接报错,当文件存在时,文件指针就会跳转到开始位置
with open('./c.txt',mode = 'rt',encoding='utf-8') as f:
    ... # 类似PASS
    print("第一次读".center(50,'*'))
    res = f.read() # 把所有的内容从硬盘中读入内存
    print(res) 
    # 读完文件后,指针在文件的最末尾,所以不会打印任何信息,如果使用with再次打开就会打印信息
    print("第二次读".center(50,'*'))
    res = f.read()
    print(res)

案例演示:

input_username = input("please input your user name : ").strip()
input_passwd = input("please input your user password : ").strip()

with open("user.txt",mode = "rt",encoding = "utf-8") as f:
    for line in f:
    # 如果是多行内容,则优先进行去除换行,再进行切分特定的符号
        username.password = line.strip().split(':')
        if input_username == username and input_passwd = password:
            print("you are login successfully")
            break
    # else 归属于for循环
    else:
        print("please check your username or password,thx") 

w 模式

1
2
3
4
5
6
7
# w 只写模式,当文件不存在时则会直接创建文件,当文件存在时,会直接清空文件,指针位置在开始位置
with open("d.txt",mode = 'wt',encoding = 'utf-8') as f:
    #f.read() 不可读,所以不能进行
    f.write("This is w mode content")
# 注意点:
# 在w模式打开文件,没有关闭文件的情况下,连续写操作,不会覆盖,文件内容则会追加写
# 如果w模式重新打开文件,则会直接清空文件内容

案例演示

1
2
3
4
5
6
7
8
# w模式用来创建全新的文件
# 文件的copy工具
src_file = input("source file : ").strip()
dest_file = input("destination file : ").strip()
with open(r'{}'.format(src_file), mode = 'rt', encoding = 'utf-8') as f1,\
    open(r'{}'.format(dest_file),mode = 'wt', encoding = 'utf-8') as f2:
    res = f1.read()
    f2.write(res)

a 模式

1
2
3
4
5
6
# a 只追加写,当文件不存在时会创建空文档,当文件存在时文件指针会直接跳转到末尾
with open('a.txt', mode = 'at', encoding = 'utf-8') as f:
    #f.read() #会直接报错,不可读
    #pass
    f.write("This is a mode content") # 会追加到文件的末尾
# 
- a模式和w模式的区别 - 相同点:打开文件不关闭的情况下,连续的写入内容都是会在原来的基础上添加 - 不同点:以a模式重新打开文件,不会清空原文件内容,会将文件指针直接移动到文件末尾。

+ 模式

不能单独使用,必须配合r、w、a模式

with open(r'a.txt', mode = 'rt+',encoding = 'utf-8') as f:
    print(f.read())

x 模式

x 模式(控制文件操作的模式)

只写模式,【不可读,不存在则创建,存在则直接报错】

b 模式

b模式:控制文件读写内容的模式

对于b模式,不进行任何转码操作,直接进行读入到内存中即可。 - 读写都是以Bytes为单位进行读写 - 任何文件都可以读写,例如mp4文件、jpg文件 - 一定不能指定字符编码参数encoding。

1
2
3
4
# 例如:读取视频文件时,使用t模式就不行,因为t模式只能读取文本文件
with open('xxx.mp4',mode = 'rb') as f: # 二进制模式,不需要指定encoding,
    f.read() # 硬盘的二进制文件直接读入内存
    f.readline() # 一次读取一行

总结: - f.read() 和 f.readlines() 都是将内容一次性读入到内存,如果内容过大会导致内存溢出。如果要将内容读入到内存中,必须分多次进行读入。两种实现方式: -

写操作

f.writelines()

# t 模式
with open(r'a.txt', mode = 'wt', encoding = 'utf-8') as f:
    f.write('111\n222\n333\n')
    l = ['11111\n','22222','33333']
    for line in l:
        f.write(line)
    f.writelines(l) # write和writelines都是一次性读取内容写入到文件中
# b 模式
# 如果是纯英文字符,直接加前缀b得到bytes类型。
l = [
    b'1111aaa\n',
    b'22222',
    b'333333'
]

# '上'.encode('utf-8') 等同于 bytes('上',encoding = 'utf-8')
l = [
    bytes('上海',encoding = 'utf-8'),
    bytes('北京',encoding = 'utf-8'),
    bytes('深圳',encoding = 'utf-8')
]

了解

1
2
3
4
5
6
7
8
with open(r'a.txt',mode = 'wt', encoding = 'utf-8') as f:
    f.write('广州')
    f.flush() # 大多数不执行,立刻将文件内容从内存刷新到硬盘中
    f.writeable() # 文件是否可读
    f.readable() # 文件是否可读
    f.closed() # 文件是否关闭
    f.encoding # 如果文件打开模式为b,打印文件的格式
    f.name # 打印文件的名字

文件指针移动

指针移动的单位都是以 bytes/字节 为单位。

只有一种情况特殊:t模式下的read(n), n表示字符的个数。

1
2
3
with open(r'aaa.txt',mode = 'rt', encoding = 'utf-8') as f:
    res = f.read(4)
    print(res)

f.seek(n,模式)

# f.seek(n,模式) :n 指的是移动的字节个数
# - 模式
#  模式 0:参照物是文件头的开头文件
f.seek(9,0)
f.seek(3.0) # 3

#  模式 1:参照物是当前指针所在位置
f.seek(9,1)
f.seek(31) # 12

#  模式 2:参照物是文件末尾位置,是倒着移动
f.seek(-9,2)
f.seek(-3.2) # 12

f.tell() # 获取文件指针当前位置

实现Linux中的tail 功能

# f.seek的应用
with open('access.log', mode = 'rt',encoding = 'utf-8') as f:
    # 将指针跳转到文件末尾
    # f.read() # 会直接报错
    f.seek(0,2) # 2是以末尾作为参照物,0是字节个数
    while True:
        f.readline() # 
        if len(line) == 0:
            time.sleep(0.3)
        else:
            print(line.decode('utf-8'),end='') # end 可以去除空格

文件修改的两种方式

1
2
3
with open(r'aaa.txt',mode='r+',encoding = 'utf-8') as f:
    f.seek(9,0)
    f.write("要写入的内容")

方式1:也就是现行文本编辑器采用的方式

1
2
3
4
5
6
7
with open(r'a.txt',mode = 'rt', encoding = 'utf-8') as f:
    res = f.read()
    data = res.replace("King","SolerHO")
    print(data)

with open(r'a.txt',mode = 'wt',encoding = 'utf-8') as f1:
    f1.write(data)

方式2:

1
2
3
4
5
6
with open(r'a.txt',mode = 'rt', encoding = 'utf-8') as f,\
    open(r'a.txt.swamp',mode = 'wt',encoding = 'utf-8') as f1:
    for line i f:
        f1.write(line.replace("King","SolerHO")) #会产生新的文件占用,所以会进行删除和重命名
os.remove('a.txt') # 删除修改前的文件
os.rename('a.txt.swamp','a.txt') # 重新修改文件名字