python-文件操作

文件操作

文件操作的基本流程

# 拿到文件句柄,打开文件
f = open("test2.txt", "r", encoding="utf8")
​
# 操作文件
data = f.read()
print(data)
​
# 关闭文件
f.close()

说明:这文件操作首先拿到了文件句柄,然后进行操作,操作完成再关闭文

# 拿到文件句柄,打开文件
f = open("test2.txt", "w", encoding="utf8")
​
# 操作文件
f.write("春风又绿江南岸\n明月何时照我还\n我本将心想明月\n怎奈明月照沟渠")
​
# 关闭文件
f.close()

 

说明:这里的写操作,开始打开文件,然后进行写操作,写操作将内容写到了内存中的缓存区中,这是因为硬盘的读写速度相对于cpu和内存的速度太慢,为了增加效率才设有这么个缓存区的。当f.close()操作之后,解释器开始将内容从缓存区中写入磁盘中

# 拿到文件句柄,打开文件
f = open("test2.txt", "w", encoding="utf8")
​
# 操作文件
f.write("春风又绿江南岸\n明月何时照我还\n我本将心想明月\n怎奈明月照沟渠\n")
​
# 刷新缓存区
f.flush()
​
f.write("煮豆燃豆萁\n豆在釜中泣\n本是同根生\n相煎何太急")
​
# 关闭文件
f.close()

 

说明:这种flush操作,每一步写操作,就flush一次,就是在写一句到缓存区,然后就写入磁盘中,因为这个flush操作的功能,我们可以使用flush制作一个进度条

# 方法1:
import time
import sys
​
for i in range(30):
    sys.stdout.write("*")   # 类似文件操作的写操作
    sys.stdout.flush()
    time.sleep(0.1)
    
    
# 方法2:
import time
​
for i in range(30):
    print("*", end="", flush=True)  # 利用print函数的flush参数
    time.sleep(0.1)

 

 

文件操作的几种模式

文件操作的几种模式分别有:r, r+, rb, w, w+, wb, a, a+

r模式

# r模式 --->r模式启动,指针从文件的最前面开始
with open("test.txt", "r", encoding="utf8") as f:
    data = f.read()
    print("data的数据内容是:", data)
    data2 = f.read()
    print("data2的数据内容是:", data2)   
    
data的数据内容是:           将军百战穿金甲,不破楼兰终不还
离离原上草,一岁一枯荣
野火烧不尽,春风吹又生
谁知盘中餐,粒粒皆辛苦
--<悯农>世上无难事,只要肯攀登
---《悯农》将军百战穿金甲,不破楼兰终不还离离原上草,一岁一枯荣野火烧不尽,春风吹又生谁知盘中餐,粒粒皆辛苦
--<悯农>世上无难事,只要肯攀登---《悯农》
data2的数据内容是: 
​

 

我们可以发现data是从文件最开头开始读取的,而第二步read操作读取到的内容是空的,是因为第一步read操作,导致指针已经到了文件的最后面了,所以是从最后面开始的,最后面没有了内容,所以是空的

w模式

# w模式--->w模式启动,如果文件不存在,创建文件再写入,如果文件存在,将文件的内容格式化清除,然后再写入
with open("test.txt", "w", encoding="utf8") as f:
    f.write("离离原上草\n一岁一枯荣\n野火烧不尽\n春风吹又生\n谁知盘中餐\n粒粒皆辛苦")
​
with open("test.txt", "r", encoding="utf8") as f:
    print(f.read())
    f.seek(9)  
    print(f.read())

 

说明:seek方法是将指针移到指定的位置,里面的参数要是3的倍数,因为一个中文字符是由3个byte组成

r+模式

r模式和r+模式类似,指针也是从最开始,r+模式除了可以读,还可以写

with open("test2.txt", "r+", encoding="utf8") as f:
    f.write("离离原上草\n一岁一枯荣\n野火烧不尽\n春风吹又生\n谁知盘中餐\n粒粒皆辛苦") # 指针到了最后面
    f.seek(0)   # 将指针移到最前面
    print(f.read())
    f.seek(9)
    print(f.read())
    
运行结果:
离离原上草
一岁一枯荣
野火烧不尽
春风吹又生
谁知盘中餐
粒粒皆辛苦
上草
一岁一枯荣
野火烧不尽
春风吹又生
谁知盘中餐
粒粒皆辛苦

 

w+模式

w+模式和w模式一样,都是先格式化清除再写入

代码省略

a模式

a模式,如果文件不存在,就创建文件,如果文件存在且有内容,此时指针在文件的最后面,就从文件的末尾追加,这种模式只能写

代码省略

a+模式

a模式是可以读写的,写的话是写到最后面

wb模式和rb模式

wb模式和 rb模式都是针对二进制数据操作的,如图片

文件操作的几种方法

文件操作的方法有写writewritelines,文件操作方法读有readreadline还有readlines

read方法

read方法既可以带参数也可以不带参数,当不带参数的时候,默认将文件的 所有内容全部读取,如果带了参数,比如read(5),是指读取指针后面的5个字符

with open("test2.txt", "r", encoding="utf8") as f:
    print(f.read(5))     # 在爬虫中,我们通常传入的参数是1024
    print(f.read(5))
    
# 读取结果
离离原上草
​
一岁一枯

 

如果文件的内容很多,我们通常通过循环的方法来读取

with open("test2.txt", "r", encoding="utf8") as f:
    data = f.read(5)
​
    while data:
        print(data)
        data = f.read(5)

 

readline方法

readline方法是一行一行读取,如果需要读取全部内容,就需要循环读取

with open("test2.txt", "r", encoding="utf8") as f:
    data = f.readline()
    while data:
        print(data.strip())
        data = f.readline()
        
        
运行结果:
离离原上草
一岁一枯荣
野火烧不尽
春风吹又生
谁知盘中餐
粒粒皆辛苦

 

readlines方法

readlines方法读取的内容是列表格式

with open("test2.txt", "r", encoding="utf8") as f:
    print(f.readlines())
    
运行结果:
['离离原上草\n', '一岁一枯荣\n', '野火烧不尽\n', '春风吹又生\n', '谁知盘中餐\n', '粒粒皆辛苦']
with open("test2.txt", "r", encoding="utf8") as f:
    datas = f.readlines()
    for data in datas:
        print(data.strip())

 

这样我们就可以通过遍历for循环取到相对应的值,或者我们想要对某行进行操作

我们想要对谁知盘中餐这一行写入悯农

# 方法1:
with open("test2.txt", "r", encoding="utf8") as f:
    datas = f.readlines()
    num = 1
    for data in datas:
        if num == 5:
            data = f"{data.strip()}--->{'《悯农》'}"
            print(data)
        else:
            print(data.strip())
        num += 1
        
运行结果:
离离原上草
一岁一枯荣
野火烧不尽
春风吹又生
谁知盘中餐--->《悯农》
粒粒皆辛苦
​
# 我们会发现上面的代码还有改进优化的地方,因为`print`函数使用了两次有些多余
with open("test2.txt", "r", encoding="utf8") as f:
​
    datas = f.readlines()
    num = 1
    for data in datas:
        if num == 5:
            data = f"{data.strip()}--->{'《悯农》'}"
        print(data.strip())
        num += 1# 继续优化
with open("test2.txt", "r", encoding="utf8") as f:
    datas = f.readlines()
    for num, data in enumerate(datas, 1):
        if num == 5:
            data = f"{data.strip()}--->{'《悯农》'}"
        print(data.strip())
        num += 1
        
# 方法2:通过列表取值的方式来改
with open("test2.txt", "r", encoding="utf8") as f:
    datas = f.readlines()
    data = f"{datas[4].strip()}---->{'《悯农》'}"
    print(data)
    
运行结果:
谁知盘中餐---->《悯农》
​
# 方法3:
with open("test2.txt", "r", encoding="utf8") as f:
    num = 1
    for data in f:
        if num == 5:
            data = f"{data.strip()}--->{'《悯农》'}"
        print(data.strip())
        num += 1
        
这里直接拿到f文件,将文件做成了一个迭代器,更提倡这种方法

 

注意:这里的修改并没有对原文件进行修改,而只是改了内存打印的数据

如果我们想要去改变原文件的内容呢?

我们实验发现没法去改变,但我们可以通过得到这个源文件的数据,然后修改,再写到另一个文件中

with open("test2.txt", "r", encoding="utf8") as f:
​
    num = 1
    for data in f:
        if num == 5:
            data = f"{data.strip()}--->{'《悯农》'}"
        print(data.strip())   # 循环读取
        f2 = open("test1.txt", "a+", encoding="utf8")
        f2.write(data)     # 循环写入
        f2.flush()
        f2.close()
        num += 1

 


       
我们可以查看test1.txt文件中的内容

writelines方法

writelinesreadlines两种方法是对应的,它写入的是列表数据,而readlines方法相应地读取列表数据

with open("test3.txt", "a", encoding="utf8")as f:
    f.writelines(["将军百战穿金甲\n", "不破楼兰终不还"])

 

seek方法和tell方法

seek方法可以随意将指针调到任意处

tell方法是指明指针的位置

 

posted @ 2020-07-07 10:04  zgzeng  阅读(191)  评论(0编辑  收藏  举报