Python系列 26 文件操作

2021/7/2 14:21:45

本文主要是介绍Python系列 26 文件操作,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

open()

Python中提供了open()方法用于对文件进行操作,该方法会返回一个文件对象。

由于被读取的文件内容本身全部属于str类型,故使用open()方法对其进行操作必然涉及字符编码的问题。

以下是open()方法的函数签名:

def open(file: Union[str, bytes, int, _PathLike[Any]], mode: str = ..., buffering: int = ..., encoding: Optional[str] = ...,
             errors: Optional[str] = ..., newline: Optional[str] = ..., closefd: bool = ...,
             opener: Optional[Callable[[str, int], int]] = ...) -> IO[Any]:

下面是对常用参数的解释:

参数名描述
file必需,文件路径(相对或者绝对路径)
mode可选,文件内容读取与操作模式,*t模式以为文本内容读取模式打开文件。需要填入encoding,b模式为二进制模式读取文件内容,默认该参数为*t 。*代表操作模式
encoding可选(Python2没有该参数),当mode为 *t 时指定编码或解码格式。一般设置为 utf-8。如不指定Windows平台默认为GBK,Mac和Linux平台为utf-8
buffering设置缓冲
errors报错级别
newline是否区分换行符,默认为True
closefd传入的file参数类型

以下是在Python3中进行读取文件的简单示例:

f = open(file="test.txt", mode="rt", encoding="utf-8")
print(f.read())  # ❶
f.close() # ❷

❶:read()读取所有内容

❷:关闭文件句柄

with语句

在open()后要切记关闭文件句柄,释放系统资源,这是一项非常重要但很容易被人忽视的细节点。

故推荐使用with语句进行文件操作,它将在with子代码块结束后自动关闭文件句柄。

with open(file="test.txt", mode="rt", encoding="utf-8") as f:
    print(f.read())

使用with语句还可以同时打开多个文件,示例如下,\可进行换行:

with open(file="test.txt",mode="rt",encoding="utf-8") as f1,\
   open(file="test2.txt",mode="rt",encoding="utf-8") as f2:
    data1 = f1.read()
    print (data1)
    data2 = f2.read()
    print (data2)

读写内容模式

t模式

当打开一个文件时,默认以*t模式打开。

t代表以文本方式读取文件内容,读取的都是字符。

with open(file="test.txt", mode="rt", encoding="utf-8") as f:
    result = f.read(3)  # ❶
    print(result)

❶:指定读取的字符数量

b模式

如果以b模式打开文件,则读取到的都是字节。

若使用字节模式打开文件,则不存在字符编码的问题

with open(file="test.txt", mode="rb") as f:
    result = f.read(3)  # ❶
    print(result)  # b'\xe6\xb5\x8b'
    hans = result.decode("utf-8")
    print(hans)  # ❷

❶:指定读取的字节数量

❷:解码

读写操作模式

r模式

r代表只读,使用r模式打开文件时文件的指针将跑到最开始。

如果文件不存在将会抛出异常,并且只能使用读取相关的方法。

with open(file="test.txt", mode="rb") as f:
    print(f.readlines())

w模式

w模式代表只写,使用w模式打开文件时就相当于新建一个文件。

如果文件已存在将清空原本文件中所有的内容,如果文件不存在则创建新文件,并且只能使用写入相关的方法。

with open(file="test.txt", mode="wb") as f:
    data = "你好世界"
    f.write(data.encode("utf-8"))

a模式

a模式为追写模式,当文件不存在时创建新文件,只能执行写相关的操作。

当文件存在时则打开文件,文件指针放到最后,所以被称为追写模式。

强调 w 模式与 a模式的异同:

  1. 相同点:在打开的文件不关闭的情况下,连续的写入,新写的内容总会跟在前写的内容之后

  2. 不同点:以 a 模式重新打开文件,不会清空原文件内容,会将文件指针直接移动到文件末尾,新写的内容永远写在最后

with open(file="test.txt", mode="ab") as f:
    f.write(b'\nnew line...')

x模式

x模式与w模式都相同。

唯一不同的地方在于如果需要打开的文件已存在,x模式会抛出异常。

而w模式会新建一个同名文件并且删除掉旧文件。

with open(file="test.txt", mode="xb") as f:
    f.write(b'\nnew line...')
    
# FileExistsError: [Errno 17] File exists: 'test.txt'

+模式

+这里是对 r w a 的一种扩展。

代表可读可写,但是打开文件后文件指针的位置还是依照 r w a 原本的位置,应该尽量少用+方法。

with open(file="test.txt", mode="r+b") as f:
    data = f.read()
    print(data)
    f.seek(0, 2)
    f.write(b"A new line again\n")

文件指针

使用seek()函数可以对文件指针进行操作。

以下是seek()函数的签名:

def seek(self, offset: int, whence: int = 0) -> int

注意,使用文件指针应该在*b模式下进行使用,它的移动将会按照字节进行移动。

如果是*t模式下,按照字符移动可能会出现某些错误。

参数描述
offset偏移量,负数代表向前移动指针,正数代表向后移动指针
whence偏移位置,0代表起始位置,1代表当前位置,2代表结束位置

示例如下:

with open(file="test.txt", mode="rb") as f:  # ❶
    print(f.tell())  # ❷
    f.seek(2, 0)
    f.seek(10, 0)
    f.seek(20, 0)
    print(f.tell())  # ❸
    f.seek(-2, 1)
    f.seek(-3, 1)
    f.seek(-4, 1)
    print(f.tell())  # ❹

# 0
# 20
# 11

❶:注意,文件指针除了(0,0)和(0,2)外,其他都应该用b模式进行。

❷:打印当前文件指针的位置 0

❸:打印当前文件指针的位置 20

❹:由于是相对定位,故可以累加。 20 - 9 ,文件指针在 11

循环读取

for循环

如果直接使用f.read(),当文件内容过于庞大时,这些内容全部会存放于Python程序的内存空间中。

会给内存带来极大的压力,故在文件较小时才使用f.read(),太大的话将使用其他解决方案,如下面的for循环进行读取:

data = b""
with open("test.txt", mode="rb") as f:
    for line in f:  # ❶
        data += line
print(data.decode("utf-8"))

❶:直接读取f代表每次读一行,以\n为单位

while循环

如果一个文件只有一行,如压缩版的前端代码。

在读取时则可使用while循环进行读取,示例如下:

data = b""
with open("test.txt", mode="rb") as f:
    while 1:
        temp = f.read(512)
        data += temp
        if not len(temp):
            break
print(data.decode("utf-8"))

文件写入

内存写入

文本编辑器的原理是在打开一个文本文件时其中所有的内容都会加载并存放至内存中。

对该文本内容的修改实际上全部都是在修改内存中的数据,当修改完成后点击保存时才会将内存的数据重新写入至硬盘中。

你应该深有体会,打开一个特别大的文本文件时速度很慢,哪怕没做任何修改保存时速度也还是很慢,实际上就是这个原因导致的。

以下是模拟内存写入,打开文件后将“计算机”替换为“电脑”:

data = ""  # ❶
with open(file="BigFileTest.txt", mode="rt", encoding="utf-8") as f:  # ❷
    while 1:
        temp = f.read(512)
        data += temp  # ❸
        print(data)  # ❹
        if not len(temp):  # ❺
            break
        
print("读取完毕..")
data = data.replace("计算机", "电脑")  # ❻

with open(file="BigFileTest.txt", mode="wt",
          encoding="utf-8") as f:  # ❼
    f.write(data)
print("写入完毕..")

❶:用于存放数据

❷:r模式的指针默认放在0位置

❸:代表每次读取512个字符

❹:这里可以做其他操作

❺:代表没有新的内容。 len(temp) == 0

❻:模拟手动修改文件内容。将计算机修改为电脑,注意此时修改的是内存中的数据

❼:读取后将Python应用程序中维护的data变量中的数据全部写入该文件。w模式会清空源文件的内容

硬盘时刷

文本编辑器的做法是在内部维护了一个变量,用于提供给用户修改内容。

这么做的好处就是用户可以在修改文件内容时能够查看到所有的文件内容,但是坏处是占用内存空间太大。

这里再介绍一种减少内存压力的方式。

注意:两种方式没有优劣之分,只有使用场景不同的区别,还是和上面一样的操作,将“计算机”替换为“电脑”。

import os

with open(file="BigFileTest.txt", mode="rt", encoding="utf-8") as f1, \
        open(file=".BigFileTest.txt.swap", mode="wt", encoding="utf-8") as f2:  # ❶
    for line in f1:
        line = line.replace("计算机", "电脑")  # ❷
        f2.write(line)  # ❸
print("操作完成..")

os.remove("BigFileTest.txt")  # ❹
os.rename(".BigFileTest.txt.swap", "BigFileTest.txt")  # ❺

这么做的坏处是没办法随时的修改内存中的变量数据,因为内存中根本没存文本文件内容。

只能按照设定好的程序走一遍,但是极大的节省了内存空间的占用。

❶:以. 开头的文件代表隐藏文件。以swap结尾的文件代表交换文件(可以理解为临时文件)

❷:每次拿到和修改的只有line

❸:写入交换文件中

❹:删除源文件

❺:修改临时文件的名字。与源文件保持一致

操作方法

以下是文件操作中常用的方法:

方法描述
read()读取某个文件(全部内容)。也可指定大小,t模式的大小为字符单位,b模式为字节单位
readline()读取一行文件内容
readlines()读取所有文件内容并返回一个列表,以行割开
write()写入一行数据,默认不会\n需要手动换行
writelines()写入一行数据,通过列表的方式写到文件里面
tell()显示当前文件光标的位置
seek()移动当前文件光标的位置(字节为单位,建议在b模式下使用)
readable()文件是否可读
writable()文件是否可写
closed文件是否关闭
encoding如果文件打开模式是b,则没有该属性
flush()立刻将文件内容从内存刷到硬盘(测试模式下使用)

Python2-open()

由于Python2中不能使用encoding参数指定编解码的方式。所以我们看看在Python2中open()应该怎样使用:

#!/usr/bin/env python2
# coding:utf-8

# import sys
# reload(sys)
# sys.setdefaultencoding('utf-8')
# 设置默认的解码方式为 utf-8。如果这样操作就不用设置decode()了。

f = open(file="test.txt",mode="rt",)
data = unicode(f.read().decode("utf-8")) # unicode()将读取出的字符转为unicode字符存储于内存中。
print data
f.close()


这篇关于Python系列 26 文件操作的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程