本次博客将从以下四个方面介绍文件操作:
- 1、文件操作介绍
- 2、os模块详解
- 3、json模块详解
- 4、pickle模块详
01 文件操作介绍
1.什么是文件?
文件对象的常用方法如下:
2.文件的作用
- 电脑中的文件包括了文档、图片、视频、程序组件等,每个类型的文件都有不同的作用或功用,
- 例如一个程序通常由主程序、动态库、配置文件等组成,这些也是文件,起到支持程序运行的作用。
- 默认数据是加载到内存中,结果 也是保存到内存中, 程序执行结束,所有的数据释放。
3.文件的打开及相关操作
- 在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件。
- 如果文件不存在那么创建,如果存在那么就先清空,然后写入数据
- 比如:open(文件名,访问模式) e.g. f = open('test.txt', 'w')
# 打开文件,默认的打开模式是'r'
f = open('pi_digits.txt')
print(f.read())
结果:
注意:没有限定访问模式的时候, 默认访问模式为读‘r’模式,这种情况下是不能进行写‘w’模式的,如下:
# 打开文件,默认的打开模式是'r'
f = open('pi_digits.txt')
print(f.read())
# io.UnsupportedOperation: not writable
f.write('hello')
可见写‘w’模式运行失败。
注意:但如果限定了文件的读取模式为读(mode=r)时,文件如果不存在,会直接报错; 就只能读已存在的文件,不能创建一个新文件了。 如下:
# mode=r, 文件doc/hello.txt不存在,直接报错,不能新建文件
f = open('doc/hello.txt,mode=r')
print(f.read())
#结果:
# FileNotFoundError: [Errno 2] No such file or directory: 'doc/hello.txt'
2)open函数多行读取文件:当文件比较大时, 使用readline方法读取.
from collections.abc import Iterable
#1)读取整个文件内容
f = open('pi_digits.txt', 'r')
print(f.read())
print('*'*50)
# 2)当文件比较大时, 使用readline方法读取.
f.seek(0, 0) # 将指针移动到文件最开始,读取第一行
print(f.readline())
f.seek(5, 0) # 将指针移动到文件最开始, 然后指针向右移动5个字节。
print(f.readline())
print(f.readline()) #读取读取紧跟着的下一行
print('*'*50)
3)open函数逐行读取文件:当文件比较小时, 使用readlines方法读取
#1)读取整个文件
from collections.abc import Iterable
f = open('pi_digits.txt', 'r')
print(f.read())
print('*'*50)
#2) 当文件比较小时, 使用read、readlines方法读取.
f.seek(0, 0) #将指针移动到文件最开始,
print(f.readlines())
4)open函数以写的方式读取文件:(f = open('doc/hello.txt', mode='w'))
# mode=w, 1). 文件不存在,会自动创建文件; 2). 只能write 3). 自动清空文件内容
f = open('doc/hello.txt', mode='w')
f.write('hello world\n')
print("写入成功......")
打开生成的文件hello.txt,会看到编辑的内容“hello world”
注意:当限定模式为写模式的时候(mode=write)的时候,是不能读取文件的,如:
# mode=w, 1). 文件不存在,会自动创建文件; 2). 只能write 3). 自动清空文件内容
f = open('doc/hello.txt', mode='w')
f.write('hello world\n')
print("写入成功......")
print("读取文件中...", f.read()) #添加读取行,结果会报错
发现此时读取文件失败了。
5)文件的附加(mode=a+)
- 如果想要给文件 添加内容,而不是覆盖 原有的内容,可以附加模式打开文件,
- 附加模式打开文件时,python不会在返回文件对象前清空文件,
- 而我们写入到文件的内容 都将添加到文件末尾,
- 如果指定 的文件不存在,python 会建一个空文件
f = open('doc/world.txt', 'a+')
# 移动指针到文件最开始
f.seek(0, 0)
print(f.read()) #可读
f.write('hello python\n') #可写(追加)
print(f.read())
注意图中打印了四个“hello python”的原因是我运行了三次程序导致的,一直运行会一直追加。
6)文件对象的属性:
f = open('doc/world.txt', 'a+')
print(f.closed) #文件未关闭,False
print(f.mode)
print(f.name)
f.close() #关闭文件
print("关闭文件后.....") #关闭后,Ture
print(f.closed)
print(f.mode)
print(f.name)
7)文件对象是可迭代对象
from collections.abc import Iterable
f = open('pi_digits.txt', 'r')
print(f.read())
print('*'*50)
# 名词: 可迭代对象: 可以通过for循环遍历的对象
print("文件对象时可迭代对象吗? ", isinstance(f, Iterable))
for index, line in enumerate(f):
print("第%s行" %(index+1), line)
8)文件与文件之间的写入:
#需求: 将hello.txt文件后5行写入pi_digits.txt文件
f1 = open('hello.txt')
tail_five_line = f1.readlines()[-5:]
print(tail_five_line)
print(len(tail_five_line))
f2 = open('pi_digits.txt', 'a+')
f2.writelines(tail_five_line)
f = open('pi_digits.txt')
print(f.read())
print("write ok")
图中原因是我运行了四遍程序导致的。
9)文件的关闭
f = open('doc/world.txt',)
print(f.read())
print(f.closed)
f.close() #关闭文件
print("关闭文件后.....")
print(f.closed)
- python中的with语句使用于对资源进行访问的场合,
- 保证不管处理过程中是否发生错误或者异常都会自动执行规定的(“清理”)操作,释放被访问的资源,
- 比如有文件读写后自动 关闭、线程中锁的自动获取和释放等。
with open('hello.txt') as f:
print('in with:', f.closed) # False
print(f.readlines()[-1]) #打印目标文件的倒数第一行内容
print('out with:', f.closed) # True
10)项目案例:文件的备份Demo(os)
import os
src_filename = input("要拷贝的文件: ")
# 1). 判断文件是否存在
if os.path.exists(src_filename):
dst_filename = input("目标文件: ")
# 2). mode='r'打开文件读取文件内容
# 注意: 要读取二进制文件,比如图片、视频等等,用'rb', 'wb', 'ab'等模式打开文件即可.
src_f = open(src_filename, 'rb')
content = src_f.read()
# 3). mode='r'打开文件写入要拷贝的文件内容
dst_f = open(dst_filename, 'wb')
dst_f.write(content)
# 4). 关闭文件对象
src_f.close()
dst_f.close()
print('拷贝成功')
else:
print("要拷贝的文件%s不存在" %(src_filename))
运行结果:
可见运行成功!
02 json模块详解
1.定义:
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。
- JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、Java、JavaScript、Perl、Python等)。
- 这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和 生成(一般用于提升网络传输速率)。
2.python类型数据和JSON数据格式互相转换规则
1.注意:python中str类型到JSON中转为unicode类型,None转为null,dict对应object; pyhton中的集合不能转成json格式。
2.
3.序列化及反序列化常用参数
如:1.编码,存储json数据,(python转json),以字典为例:
import json
info = dict(user1='00000', user2='11111', 用户3='33333')
# 编码: 1)字典转成json数据格式
json_info = json.dumps(info)
print(info, json_info)
print(type(info), type(json_info))
# 编码: 2)字典转成json并存储未文件
json.dump(info, open('doc/info.json', 'w'), indent=4, ensure_ascii=False)
print("写入json文件成功")
可见转json并 文件存储成功,此时我们直接查看是不能识别所有的信息的。那么就需要对json文件 进行加载。
如:2.解码,加载json文件:(json转python):
import json
filename = 'doc/info.json'
# 3)解码: 将文件中的json数据转换成python对象进行处理
python_info = json.load(open(filename))
print(python_info)
print(python_info.get('用户3'))
4.自定义复杂数据类型编解码
import datetime,json
def time2str(obj):
#python to json
if isinstance(obj,datetime.datetime):
json_str = {"datetime":obj.strftime.datetime("%Y-%m-%d %X")}
return json_str
def str2time(json_obj):
#json to python
if "datetime" in json_obj:
date_str,time_str = json_obj["datetime"].spllit('')
date = [int(x) for x in date_str.split('_')]
time = [int(x) for x in time_str.split(':')]
dt = datetime.datetime(date[0],date[0],date[1],date[2],time[0],time[1],time[2])
return dt
return json_obj
dt = datetime.datetime.now()
a = json.dumps(dt,default=time2str)
print(a)
print(json.loads(a,object_hook=str2time))
#{"datetime":2019-12-17 10:57:35"}
#2019-12-17 10:57:35
2)
from datetime import datetime
from datetime import date
import json
def time2str(dateObj):
return str(dateObj)
dt = datetime.now()
today = date.today()
# 自定义编码和解码
with open('doc/date.json', 'w') as f:
# Object of type date is not JSON serializable
json.dump(today, f, default=time2str)
print('dump ok')
注意:json的缺点:不能存储集合类型,python特有的日期类型不能存储,自定义对象不能存储,因此引入了pickle模块。
03 pickle模块(仅支持python)
1.定义
- python的pickle模块实现了python的所有数据序列和反序列化。与JSON不同的是pickle不是用于多种语言间的数据传输,
- 它仅作为python对象的持久化或者python程序间进行互相传输对象的方法,
- 因此它支持了python所有的数据类型。
- cPickle是pickle模块的C语言编译版本相对速度更快。
2.json和pickle模块的区别
- JSON只能处理基本数据类型。pickle能处理所有Python的数据类型。
- JSON用于各种语言之间的字符转换。
- pickle用于Python程序对象的持久化或者Python程序间对象网络传输,
- 但不同版本的Python序列化可能还有差异
3.pickle数据的序列化
和json转换方式类似:python>>>>>>pickle-----(dump)
pickle>>>>>>>python-----(load)
import pickle
# 1)编码
from datetime import date
today = date.today()
with open('date.pkl', 'wb') as f:
pickle.dump(today, f)
print('pickle dump ok')
# 2)解码: 反序列化
with open('date.pkl', 'rb') as f:
today = pickle.load(f)
print('pickle load ok')
print(today)
5.小拓展(忽略注释行)
filename = 'doc/passwd.bak'
with open(filename) as f:
for line in f:
if not line.startswith('#'):
print(line)
文件'doc/passwd.bak'的前10行,可见2,3,4行为注释行,运行结果我们看一下。
可见 被注释的2,3,4行被忽略了,直接跳过从第五行读取了。