目录
第八章 IO流及其对象序列化
8.1 IO流
8.1.1 什么是IO流
IO流 input output stream
主要是计算机的输入和输出的操作
侠义:常见IO流操作是指的是内存和磁盘之间的输入和输出的操作
IO流的操作是一种持久化操作方式,将数据持久化到磁盘上
python如何操作IO流?
open()全局函数
open(file, mode='r')
file --------- 表示的是打开或者操作文件的文件名称或者文件的路径
mode='r' ------- 指的是打开的模式(默认值r read 默认的是字符流)
'r' open for reading (default) 'w' open for writing, truncating the file first 'x' create a new file and open it for writing 'a' open for writing, appending to the end of the file if it exists
>>> import os.path as p >>> p.abspath(".") 'C:\\Users\\WX' >>> open("a.txt") <_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'> >>> f = open("a.txt") >>> f <_io.TextIOWrapper name='a.txt' mode='r' encoding='cp936'> >>> dir(f) ['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines'] >>> f = open("a.txt") >>> f.read() '哈哈哈哈哈哈哈哈哈哈哈哈哈' >>> f.read() '' >>> f.read() '' >>> f.close()
8.1.2 流的分类
根据数据流的流动方向(站在内存的角度来讲):输入流 输出流
把数据存储到磁盘上这是输入流还是输出流?------ 输出流
根据数据的类型:字符流 字节流
8.2 字符流
>>> f = open("a.txt",mode="r") >>> f.read() '哈哈哈哈哈哈哈哈哈哈哈哈哈' >>> f.close() >>> f = open("a.txt",mode = "w") >>> f.write("嘿嘿嘿嘿嘿嘿嘿嘿嘿") 9 >>> f.close() >>> f = open("a.txt",mode = "w") >>> f.write("呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵") 18 >>> f.flush() >>> f.close()
一旦关闭了流,下一次写入的内容会覆盖掉上一次的内容
如何做到不覆盖?
>>> f = open("b.txt",mode = "a") >>> f.write("哈哈哈哈哈哈哈哈") 8 >>> f.flush() >>> f.close() >>> f = open("b.txt",mode = "a") >>> f.write("呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵") 18 >>> f.close()
注意:本质上mode="r" ------ node="rt" t ---- text字符流
>>> f = open("b.txt",mode = "at") >>> f.write("呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵") 18 >>> f.close()
>>> f = open("b.txt",mode = "rt") >>> f.read(2) '哈哈' >>> f.read(4) '哈哈哈哈' >>> f.read(8) '哈哈呵呵呵呵呵呵' >>> f.read(12) '呵呵呵呵呵呵呵呵呵呵呵呵' >>> f.close()
8.3 字节流
b ------- binary mode
视频、图片、音频、可执行的二进制文件都是二进制数据,使用字节流
mode = "rb" ----- 表示的是字节流的操作IO
>>> f = open("a.jpg","r") >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 0: illegal multibyte sequence >>> f.close() >>> f = open("a.jpg","rb") >>> f.read()
注意:字节流操作过大的数据的时候不建议一次性读取
字节可以操作任何数据,但是字符只能操纵字符数据
>>> f.close() >>> f = open("a.txt","rb") >>> f.read() b'\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7\xba\xc7'
字节数据的备份:
>>> f = open("a.jpg","rb") >>> ff = open("b.jpg","wb") >>> ff.write(f.read()) 891024 >>> f.close() >>> ff.close()
#需要将D:\重大城科\上课录屏\18_登录注册习题讲解.mp4视频文件被分到桌面上C:\Users\WX\Desktop\18_登录注册习题讲解.mp4 def copy_file(src,dest): f = open(src,"rb") ff = open(dest,"wb") ff.write(f.read()) f.close() ff.close() copy_file("D:\\重大城科\\上课录屏\\18_登录注册习题讲解.mp4","C:\\Users\\WX\\Desktop\\18_登录注册习题讲解.mp4")
#需要将D:\重大城科\上课录屏\18_登录注册习题讲解.mp4视频文件被分到桌面上C:\Users\WX\Desktop\18_登录注册习题讲解.mp4 def copy_file(src,dest): f = open(src,"rb") ff = open(dest,"wb") # ff.write(f.read()) #以M为单位去读取 1M = 1024*1024 while True: data = f.read(1024*1024) if data == b"": print("读取完成了!!!!") break else: ff.write(data) f.close() ff.close() copy_file("D:\\重大城科\\上课录屏\\18_登录注册习题讲解.mp4","C:\\Users\\WX\\Desktop\\18_登录注册习题讲解.mp4")
请输入你要备份的文件的数据路径:D:\重大城科\上课录屏\18_登录注册习题讲解.mp4
请输入你要保存备份文件的路径:C:\Users\WX\Desktop\18_登录注册习题讲解.mp4
#需要将D:\重大城科\上课录屏\18_登录注册习题讲解.mp4视频文件被分到桌面上C:\Users\WX\Desktop\18_登录注册习题讲解.mp4 def copy_file(): src = input("请输入你要备份的文件的数据路径:") dest = input("请输入你要保存备份文件的路径:") f = open(src,"rb") ff = open(dest,"wb") # ff.write(f.read()) #以M为单位去读取 1M = 1024*1024 while True: data = f.read(1024*1024) if data == b"": print("读取完成了!!!!") break else: ff.write(data) f.close() ff.close() # copy_file("D:\\重大城科\\上课录屏\\18_登录注册习题讲解.mp4","C:\\Users\\WX\\Desktop\\18_登录注册习题讲解.mp4") copy_file()
请输入你要备份的文件的数据路径:D:\重大城科\上课录屏\18_登录注册习题讲解.mp4
请输入你要保存备份文件的路径:C:\Users\WX\Desktop
import os.path as p #需要将D:\重大城科\上课录屏\18_登录注册习题讲解.mp4视频文件被分到桌面上C:\Users\WX\Desktop\18_登录注册习题讲解.mp4 def copy_file(): src = input("请输入你要备份的文件的数据路径:") dest = input("请输入你要保存备份文件的路径:") filename = src[src.rfind("\\")+1:] f = open(src,"rb") # ff = open(dest,"wb") ff = open(p.join(dest,filename),"wb") # ff.write(f.read()) #以M为单位去读取 1M = 1024*1024 while True: data = f.read(1024*1024) if data == b"": print("读取完成了!!!!") break else: ff.write(data) f.close() ff.close() # copy_file("D:\\重大城科\\上课录屏\\18_登录注册习题讲解.mp4","C:\\Users\\WX\\Desktop\\18_登录注册习题讲解.mp4") copy_file() #D:\\重大城科\\上课录屏\\python0316\\18_登录注册习题讲解.mp4
如果备份的文件的名称相同的情况下,会覆盖掉上一次备份的文件
使用uuid
import os.path as p import uuid #需要将D:\重大城科\上课录屏\18_登录注册习题讲解.mp4视频文件被分到桌面上C:\Users\WX\Desktop\18_登录注册习题讲解.mp4 def copy_file(): src = input("请输入你要备份的文件的数据路径:") dest = input("请输入你要保存备份文件的路径:") filename = src[src.rfind("\\")+1:] random_uuuid = uuid.uuid4().hex filename = random_uuuid + filename f = open(src,"rb") # ff = open(dest,"wb") ff = open(p.join(dest,filename),"wb") # ff.write(f.read()) #以M为单位去读取 1M = 1024*1024 while True: data = f.read(1024*1024) if data == b"": print("读取完成了!!!!") break else: ff.write(data) f.close() ff.close() # copy_file("D:\\重大城科\\上课录屏\\18_登录注册习题讲解.mp4","C:\\Users\\WX\\Desktop\\18_登录注册习题讲解.mp4") copy_file() #D:\\重大城科\\上课录屏\\python0316\\18_登录注册习题讲解.mp4
也可以加上时间戳 time.time()
完成某个磁盘或者某个文件夹的备份
8.4 对象序列化
8.4.1 什么是对象序列化
对象:万物皆对象 在python中 容器(元组 列表 集合 字典) 函数
如果想要将对象持久化,保存到磁盘上,就需要对象序列化
对象序列化:将内存中像对象这种抽象的概念转换为真正字符或者字节数据存储到磁盘上
8.4.2 pickle模块
对象序列化为字节数据
>>> import pickle >>> dir(pickle) ['ADDITEMS', 'APPEND', 'APPENDS', 'BINBYTES', 'BINBYTES8', 'BINFLOAT', 'BINGET', 'BININT', 'BININT1', 'BININT2', 'BINPERSID', 'BINPUT', 'BINSTRING', 'BINUNICODE', 'BINUNICODE8', 'BUILD', 'BYTEARRAY8', 'DEFAULT_PROTOCOL', 'DICT', 'DUP', 'EMPTY_DICT', 'EMPTY_LIST', 'EMPTY_SET', 'EMPTY_TUPLE', 'EXT1', 'EXT2', 'EXT4', 'FALSE', 'FLOAT', 'FRAME', 'FROZENSET', 'FunctionType', 'GET', 'GLOBAL', 'HIGHEST_PROTOCOL', 'INST', 'INT', 'LIST', 'LONG', 'LONG1', 'LONG4', 'LONG_BINGET', 'LONG_BINPUT', 'MARK', 'MEMOIZE', 'NEWFALSE', 'NEWOBJ', 'NEWOBJ_EX', 'NEWTRUE', 'NEXT_BUFFER', 'NONE', 'OBJ', 'PERSID', 'POP', 'POP_MARK', 'PROTO', 'PUT', 'PickleBuffer', 'PickleError', 'Pickler', 'PicklingError', 'PyStringMap', 'READONLY_BUFFER', 'REDUCE', 'SETITEM', 'SETITEMS', 'SHORT_BINBYTES', 'SHORT_BINSTRING', 'SHORT_BINUNICODE', 'STACK_GLOBAL', 'STOP', 'STRING', 'TRUE', 'TUPLE', 'TUPLE1', 'TUPLE2', 'TUPLE3', 'UNICODE', 'Unpickler', 'UnpicklingError', '_Framer', '_HAVE_PICKLE_BUFFER', '_Pickler', '_Stop', '_Unframer', '_Unpickler', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_compat_pickle', '_dump', '_dumps', '_extension_cache', '_extension_registry', '_getattribute', '_inverted_registry', '_load', '_loads', '_test', '_tuplesize2code', 'bytes_types', 'codecs', 'compatible_formats', 'decode_long', 'dispatch_table', 'dump', 'dumps', 'encode_long', 'format_version', 'io', 'islice', 'load', 'loads', 'maxsize', 'pack', 'partial', 're', 'sys', 'unpack', 'whichmodule']
dumps -------- 将对象序列化为字节数据
>>> ls = [1,2,3,4,5,6,7] >>> type(ls) <class 'list'> >>> pickle.dumps(ls) b'\x80\x04\x95\x13\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03K\x04K\x05K\x06K\x07e.' >>> data = pickle.dumps(ls) >>> data b'\x80\x04\x95\x13\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03K\x04K\x05K\x06K\x07e.' >>> f = open("a.dat","wb") >>> f.write(data) 30 >>> f.close()
dump ----- 将对象序列化为字节数据,并且能够保存到文件中
>>> f.close() >>> pickle.dump(ls,open("b.dat","wb"))
loads ------- 将字节数据反序列化为对象
>>> f = open("a.dat","rb") >>> show = f.read() >>> show b'\x80\x04\x95\x13\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03K\x04K\x05K\x06K\x07e.' >>> pickle.loads(show) [1, 2, 3, 4, 5, 6, 7] >>> ls1 = pickle.loads(show) >>> ls1 [1, 2, 3, 4, 5, 6, 7] >>> type(ls1) <class 'list'>
load ----- 将file反序列化为对象
>>> pickle.load(open("b.dat","rb")) [1, 2, 3, 4, 5, 6, 7]
8.4.3 json模块
将对象序列化为字符数据
>>> d = {"username":"zhangsan","age":18,"gender":"男"} >>> type(d) <class 'dict'> >>> import json >>> dir(json) ['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner'] >>> json.dumps(d) '{"username": "zhangsan", "age": 18, "gender": "\\u7537"}' >>> s = json.dumps(d) >>> s '{"username": "zhangsan", "age": 18, "gender": "\\u7537"}' >>> type(s) <class 'str'> >>> f = open("a.txt","w") >>> f.write(s) 55 >>> f.close() >>> ff = open("a.txt","r") >>> ff.read() '{"username": "zhangsan", "age": 18, "gender": "\\u7537"}' >>> ff.clse() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: '_io.TextIOWrapper' object has no attribute 'clse' >>> ff.close() >>> ff = open("a.txt","r") >>> dd = ff.read() >>> dd '{"username": "zhangsan", "age": 18, "gender": "\\u7537"}' >>> type(dd) <class 'str'> >>> ddd = json.loads(dd) >>> ddd {'username': 'zhangsan', 'age': 18, 'gender': '男'} >>> type(ddd) <class 'dict'>
总结:json模块一般是用来序列化字典对象,单并不是只能序列化字典对象(Python2中只能操作字典对象)
>>> ls [1, 2, 3, 4, 5, 6, 7] >>> json.dumps(ls) '[1, 2, 3, 4, 5, 6, 7]'