永久存储:文件处理与路径处理

本文介绍了如何在Python中永久性地将数据保存到硬盘,强调了正确操作文件以避免数据丢失。详细讲解了使用`pathlib`模块进行文件系统路径操作,包括创建、读取、写入、删除文件及目录的方法,以及利用with语句进行文件处理以确保文件正确关闭。此外,文章还涵盖了相对路径与绝对路径的转换,以及文件的读写模式和二进制文件的处理。
摘要由CSDN通过智能技术生成

💡大纲

⭕如何将数据永久的存放到硬盘上

👉不要打开文件,然后直接关闭文件,会导致截断

 一、如何操作文件

f = open("FishC.txt","w")
f.write("I Love Python\n") # 返回字符串长度
f.writelines(["I Love FishC\n","I Love my wife\n"])
f.close()

f = open("FishC.txt","r+") # 以追加的模式,可读可写
f.readable() # true
f.writable() # True

for each in f:
    print(each)
    
f.read() # 读取是空字符串,因为文件指针在末尾EOF

f.tell()

f.seek(0) # 将文件指针移到开头

f.readline()
f.read()
f.write("I Love Wifi")

f.flush() # 不用关闭文档就能读取

f.truncate(29) # 截取到29
f.close()

 

二、pathlib --- 面向对象的文件系统路径

💡pathlib 是 Python3.4 之后新添加的模块,它可以让文件和路径操作变得快捷方便,完美代替 os.path 模块。

(一)模块概述

💡提供了用于表示文件系统路径的类

  • 路径类       
    • 提供纯计算操作而不涉及 I/O 的 PurePath
    • 从纯路径继承而来但提供 I/O 操作的 Path

(二)基本用法

1、导入模块

from pathlib import Path

2、访问当前目录的路径:Path.cwd()

Path.cwd() # WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small')

3、创建一个文件对象并添加文件名

p = Path('c:/Users/13601/Desktop/My_Paper/Paper_Small')
q = p / "FishC.txt"

 4、判断文件对象是不是文件夹/文件:文件对象.is_dir()/文件对象.is_file()

p.is_dir() # True
q.is_file() # True

5、判断路径是否存在:文件对象.exists()

p.exists() # True
Path("c:/404").exists() # False

 6、获取目录路径的最后一部分:文件对象.name

p.name # 'Paper_Small'
q.name # 'FishC.txt'

7、获取文件名:文件对象.stem

q.stem # 'FishC'

 8、获取文件后缀:文件对象.suffix

q.suffix # '.txt'

9、获取父级目录 :文件对象.parent

p.parent # WindowsPath('c:/Users/13601/Desktop/My_Paper')
q.parent

10、获取逻辑祖先路径构成的序列 

ps = p.parents 
for each in ps:
    print(each)
''' 
c:\Users\13601\Desktop\My_Paper
c:\Users\13601\Desktop
c:\Users\13601
c:\Users
c:\
'''

ps[0] # WindowsPath('c:/Users/13601/Desktop/My_Paper')

 11、将路径的各个组件拆分为元组:文件对象.parts

p.parts # ('c:\\', 'Users', '13601', 'Desktop', 'My_Paper', 'Paper_Small')

12、查询文件或文件夹的信息:文件对象.stat()

p.stat()

相对路径与绝对路径

13、.表示当前目录,..表示上级目录

Path("./VMD_Source") # WindowsPath('VMD_Source')
Path("../VMD— python.txt") # WindowsPath('../VMD— python.txt') 上一级目录中的

14、将相对路径转换为绝对路径:文件对象.resolve()

Path("./VMD_Source").resolve() 
# WindowsPath('C:/Users/13601/Desktop/My_Paper/Paper_Small/VMD_Source')

15、获取当前路径下所有子文件和子文件夹:文件对象.iterdir()

p.iterdir()
for each in p.iterdir():
    print(each) # 获得所有的子文件/文件夹

💡获取所有的子文件夹,并组成一个列表

[x for x in p.iterdir() if x.is_dir()]
'''
[WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small/.vscode'),
 WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small/All_Paper_Read'),
 WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small/pyswarm'),
 WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small/VMD_Source'),
 WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small/__pycache__'),
 WindowsPath('c:/Users/13601/Desktop/My_Paper/Paper_Small/论文综述')]
'''

16、创建文件夹/文件

💡 在一个文件对象p后面加 / 和想要创建的文件名得到文件对象n,然后调用n.mkdir()进行创建,得到的新文件夹就是在当前目录路径下的

👉如果想要创建的文件夹已经存在,再创建的话会报错,可以设置参数exist_ok=True

👉如果想要创建的文件夹有多个虚假的父级目录也会报错,可以设置参数parents=True

n = p/"FishC"
n.mkdir()
n.mkdir(exist_ok=True) # 重复创建不会报错

n = p/"FishC/A/B/C"
n.mkdir(parents=True,exist_ok=True) 
# "C:\Users\13601\Desktop\My_Paper\Paper_Small\FishC\A\B\C" 直接创建虚假的父级目录
n = n / "FishC.txt"
f = n.open('w')
f.write("I Love FishC.")
f.close()

17、删除文件/文件夹:文件对象.unlink()/文件对象.parent.rmdir()

n.unlink() # 删除待删除文件夹里面的文件
n.parent.rmdir() # 删除n的父级文件夹

 18、查找文件:文件对象.glob(查找内容)

p = Path('.') # 访问当前目录
p.glob("*.txt") # 查找后缀为.txt的文件
list(p.glob("*.txt")) # [WindowsPath('FishC.txt')]
list(p.glob("*/*.pdf")) # 当前路径下的下一级目录中所有包含.pdf后缀的文件
list(p.glob("**/*.pdf")) # 查找当前目录以及该目录下的所有子目录

三、with语句和上下文管理器

(一)文件的打开

💡首先需要知道文件打开的通用格式是什么

with open("文件路径", "文件打开模式", encoding = "操作文件的字符编码") as f:
    "对文件进行相应的读写操作"

👉文件路径:相对路径、绝对路径

👉文件打开模式:只读、只写、追加、可读可写、二进制模式、文本模式等(后续会详细说明)

👉字符编码:utf-8(万国码)、gbk(中文编码)

👉文件对应的读写操作就涉及到相关函数了(后续详细说)

👉f 是创建的文件对象吧(我理解为文件指针,指向打开的文件)

⚠️这是使用with块的原因是,with块在执行完毕后,自动对文件进行关闭操作

1、文件路径

👉如果文件与程序不在同一文件夹中,一般需要用到绝对路径来进行访问

👉程序与文件在同一文件夹,可简化成文件名,使用相对路径

2、打开模式

⚠️打开模式可以缺省,默认为只读模式

  • "r" :只读模式,如文件不存在,报错

  • "w":覆盖写模式,如文件不存在,则创建;如文件存在,则完全覆盖原文件

  • "x":创建写模式,如文件不存在,则创建;如文件存在,报错

  • "a":追加写模式,如文件不存在,则创建;如文件存在,则在原文件后追加内容

  • "b":二进制文件模式,不能单独使用,需要配合使用如"rb","wb","ab",该模式不需指定encoding

  • "t":文本文件模式,默认值,需配合使用 如"rt","wt","at",一般省略,简写成如"r","w","a"

  • "+":与"r","w","x","a"配合使用,设置为可读可写

💡二进制文件 

# 图片:二进制文件,不需要字符编码
with open("test.jpg", "rb") as f:    
    print(len(f.readlines())) # 将每行列为列表计算长度

3、字符编码

👉万国码(utf-8):包含全世界所有国家需要用到的字符

👉中文编码(gbk):解决中文编码问题

⚠️在windows系统下,如果缺省,则默认为gbk,并且不建议缺省encoding

⚠️解码模式要匹配

(二)文件的读取

1、读取整个内容---f.read() 读取数据的长度(单位:字节)

with open("测试文件_utf.txt", "r", encoding="utf-8") as f:      
    text = f.read()                                                   
    print(text)

2、逐行进行读取---f.readline()

with open("测试文件_gbk.txt", "r", encoding="gbk") as f:     
    for i in range(3): # 读取前三行
        text = f.readline() # 每次只读取一行
        print(text) # 这种方式会有两次换行,原文一次(如果文件中有换行的话),print自带一次
        print(text, end="") # 保留原文的换行,使print()的换行不起作用

3、读入所有行,以每行为元素形成一个列表---f.readlines()

with open("测试文件_gbk.txt", "r", encoding="gbk") as f:
    text = f.readlines() # 注意每行末尾有换行符
    print(text, end="") # 使print()的换行不起作用  
'''
['临江仙·滚滚长江东逝水\n', '滚滚长江东逝水,浪花淘尽英雄。\n', '是非成败转头空。\n', '\n', '青山依旧在,几度夕阳红。\n', '白发渔樵江渚上,惯看秋月春风。\n', '一壶浊酒喜相逢。\n', '古今多少事,都付笑谈中。\n']
'''  

⭕总结

  • 文件比较大时,read()和readlines()占用内存过大,不建议使用
  • readline用起来不是很方便
  • 可以通过从迭代对象中取值的方式读取
with open("测试文件_gbk.txt", "r", encoding="gbk") as f:     
    for text in f: # f本身就是一个可迭代对象,每次迭代读取一行内容 
        print(text,end="")  

(三)文件的写入

1、向文件写入一个字符串或字节流(二进制)---f.write()

with open("测试文件.txt", "w", encoding="utf-8") as f:                      
        f.write("啦啦啦啦啦啦\n") # 如需换行,末尾加换行符\n

⚠️如果文件存在,新写入内容会覆盖掉原内容,一定要注意!!!

⚠️文件不存在则立刻创建一个

👉以追加"a" 的模式写入,在原文的末尾开始写入

with open("测试文件.txt", "a", encoding="utf-8") as f:                      
        f.write("姑娘你别哭泣\n")        
        f.write("我俩还在一起\n")        
        f.write("今天的欢乐\n")
        f.write("将是明天创痛的回忆\n")

2、将一个元素为字符串的列表整体写入文件---f.writelines()

⚠️与readlines()相对应

ls = ["春天刮着风", "秋天下着雨", "春风秋雨多少海誓山盟随风远去"] # 需要换行就加\n
with open("测试文件.txt", "w", encoding="utf-8") as f:
    f.writelines(ls)
# 春天刮着风秋天下着雨春风秋雨多少海誓山盟随风远去

(四)可读可写

💡对于文件的创建与否,仍然以未加+的打开模式为准

1、"r+"

  • 如果文件名不存在,则报错

  • 指针在开始,需要要把指针移到末尾才能开始写,否则会覆盖前面内容

⭕ 将指针移到末尾的方法

👉第一种:将文件内容全部读取一遍,这猴子那个方法很笨,不建议

for line in f:
    print(line) # 全部读一遍后,指针到达结尾

 👉第二种:可以将指针移到末尾f.seek(偏移字节数,位置(0:开始;1:当前位置;2:结尾))

with open("测试文件.txt", "r+", encoding="gbk") as f:
    f.seek(0,2) 
    text = ["啦啦啦啦啦,\n", "噜噜噜噜。\n"]
    f.writelines(text)

2、"w+"

  • 若文件不存在,则创建

  • 若文件存在,会立刻清空原内容!!!

with open("测试文件.txt", "w+", encoding="gbk") as f:
    pass # 文件存在,清空原内容

with open("测试文件.txt", "w+", encoding="gbk") as f:
    text = ["啦啦啦啦啦,\n", "噜噜噜噜。\n"]
    f.writelines(text) # 写入新内容,指针在最后
    f.seek(0,0) # 指针移到开始
    print(f.read()) # 读取内容

3、"a+"

  • 若文件不存在,则创建

  • 指针在末尾,添加新内容,不会清空原内容

with open("测试文件.txt", "a+", encoding="gbk") as f:
    f.seek(0,0) # 因为是追加的形式,所以要把指针移到开始进行读取
    print(f.read()) # 读取内容

with open("测试文件.txt", "a+", encoding="gbk") as f:
    text = ["啦啦啦啦啦,\n", "噜噜噜噜。\n"]
    f.writelines(text) # 指针在最后,追加新内容 
    f.seek(0,0) # 指针移到开始
    print(f.read()) # 读取内容

(五)数据的存储与读取(了解即可)

💡两种数据存储结构csv和json

1、csv格式

👉由逗号将数据分开的字符序列,可以由excel打开

# 读取
with open("成绩单.csv", "r", encoding="gbk") as f:
    ls = [] 
    for line in f: # 逐行读取
        ls.append(line.strip("\n").split(",")) # 去掉每行的换行符,然后用“,”进行分割
for res in ls:
    print(res)
'''
['编号', '数学成绩', '语文成绩']
['1', '100', '98']
['2', '96', '99']
['3', '97', '95']
'''

# 写入
ls = [['编号', '数学成绩', '语文成绩'], ['1', '100', '98'], ['2', '96', '99'], ['3', '97', '95']]
with open("score.csv", "w", encoding="gbk") as f: 
    for row in ls:                                  
        f.write(",".join(row)+"\n") # 用逗号组合成字符串形式,末尾加换行符

2、json格式

👉常用来存储字典类型

import json
scores = {"Petter":{"math":96 , "physics": 98},
        "Paul":{"math":92 , "physics": 99},
        "Mary":{"math":98 , "physics": 97}}

# 写入---dump()
with open("score.json", "w", encoding="utf-8") as f: # 写入整个对象 
        # indent 表示字符串换行+缩进 ensure_ascii=False 显示中文
        json.dump(scores, f, indent=4, ensure_ascii=False)  
 
# 读取---load()
with open("score.json", "r", encoding="utf-8") as f:                                         
        scores = json.load(f) # 加载整个对象
        for k,v in scores.items():
            print(k,v)
'''
Petter {'math': 96, 'physics': 98}
Paul {'math': 92, 'physics': 99}
Mary {'math': 98, 'physics': 97}
'''

(六)将python对象序列化:pickle

💡将python对象转换为二进制字节流

import pickle

x,y,z = 1,2,3
s = "FishC"
l = ["小甲鱼",520,3.14]
d = {"one":1,"two":2}

with open("data.pkl",'wb') as f:
    pickle.dump((x,y,z,s,l,d),f)
import pickle

with open("data.pkl",'rb') as f:
    x,y,z,s,l,d = pickle.load(f)

print(x,y,z,s,l,d,sep='\n')

 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盾山狂热粉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值