Python文件操作补充

x模式(控制文件操作的模式)
x, 只写模式【不可读;不存在则创建,存在则报错】

代码:
with open('e.txt',mode='xt',encoding='utf-8') as f:
f.write("哈哈哈") #执行第一次在该文件夹下创建e.txt并写入“哈哈哈”,第二次启动程序是报错,原因为存在e.txt文件
#报错信息为:FileExistsError: [Errno 17] File exists: 'e.txt'

b模式(控制文件读写内容的模式,与t模式相对):

控制文件读写内容的模式
t:
1、读写都是以字符串(unicode)为单位
2、只能针对文本文件
3、必须指定字符编码,即必须指定encoding参数
b:binary模式
1、读写都是以bytes为单位
2、可以针对所有文件
3、一定不能指定字符编码,即一定不能指定encoding参数

总结:
1、在操作纯文本文件方面t模式帮我们省去了编码与解码的环节,b模式则需要手动编码与解码,所以此时t模式更为方便
2、针对非文本文件(如图片、视频、音频等)只能使用b模式
"""

代码:

with open(r'test.jpg',mode='rt',encoding='utf-8') as f:  #目录下有test.jpg文件,用t模式打开并指定了字符编码报错
f.read()
报错信息:‘utf-8' codec can't decode byte 0xff in position 0: invalid start byte
 
with open(r'test.jpg',mode='rb') as f:  #这里不能指定字符编码
res=f.read() # 硬盘的二进制读入内存—>b模式下,不做任何转换,直接读入内存
print(res) # bytes类型—》当成二进制 但是python会把二进制封装成方便操作的数据类型,这里就是bytes类型
print(type(res)) #这里的res的数据类型为<class 'bytes'>

with open(r'd.txt',mode='rb') as f:
res=f.read() # utf-8的二进制,磁盘里面的二进制直接拿出来,没有做任何转换,只是充当数据的搬运工(三个字节对应一个中文)
print(res,type(res)) #这里需要注意的是未解码之前python解释器会将英文和数字以b'XXX'的形式打印出来
print(res.decode('utf-8')) #手动解码

 with open(r'e.txt',mode='wb') as f:
f.write('你好hello'.encode('gbk')) #不能直接写”你好hello",会报错,报错大致内容是需要一bytes liked对象而不是str
 with open(r'f.txt',mode='wb') as f:
f.write('你好hello'.encode('utf-8')) #最好用一种编码,要不会乱啊,增加烦恼,你这么写读的时候总会乱码,以Pycharm编辑器为例,默认编码是utf-8
f.write('哈哈哈'.encode('gbk'))

案例:以b模式实现文件拷贝功能

#文件拷贝功能的实现
last_file=input("请输入你的源文件路径").strip()
new_file=input("请输入你的目标文件路径").strip()
with open(r'{}'.format(last_file),mode='rb')as f1,\
open(r'{}'.format(new_file),mode='wb') as f2:
for line in f1: #分行写入,防止直接全部读入内存
f2.write(line)
    # res=f1.read() # 如果这样写,内存占用过大
# f2.write(res)



两种读入调优策略
#1指定读入的数据量
 with open(r'test.jpg',mode='rb') as f:
while True:
res=f.read(1024) #除了在t模式read()内指定的是字符数,其他情况只的都是字节数
if len(res)==0 :
break
print(res)

#2一行一行读,大多数情况下,文件中每一行的数据都是比较精简的
with open(r'test.jpg',mode='rb') as f:
for line in f:
print(line,len(line))

#文件操作的其他方法

# 一:读相关操作
# 1、readline:一次读一行
with open(r'g.txt',mode='rt',encoding='utf-8') as f:
res1=f.readline()
res2=f.readline() #指针是会移动的
print(res2)

#2:以readline遍历完文件中所有数据
with open(r'db.txt',mode='rt',encoding='utf-8') as f:
while True:
res=f.readline()
if len(res)==0 :
break
print(res)
#3:readlines  得到的结果是一个大列表,一行占一个位置
with open(r'db.txt',mode='rt',encoding='utf-8') as f:
res=f.readlines()
print(res)
#本段代码的输出结果为:['yanjialuo:123\n', 'shizhongwen:1234\n', 'taozongguo:23456']
#强调:read()和readlines()方法都是将文件中的数据一次性得全部读入内存,如果文件数据过大,将会导致内存溢出。
#二:写相关操作
#1writelines() 这里所指的是不是写多行的意思???答案是不是,他是将一个列表按位置以行写入内存
# f.writelines():
# with open('h.txt',mode='wt',encoding='utf-8') as f:
# # f.write('1111\n222\n3333\n') #能写多行啊,writelines不是这个意思
#
# # l=['11111\n','2222','3333',4444] #444写不进去,int类型不行,必须为str类型
# l=['11111\n','2222','3333']
# # for line in l:
# # f.write(line)
# f.writelines(l) #相当于调用一个for循环,把for循环的内容写到文件中去了


# with open('h.txt', mode='wb') as f:
# # l = [
# # '1111aaa1\n'.encode('utf-8'),
# # '222bb2'.encode('utf-8'),
# # '33eee33'.encode('utf-8')
# # ]
#
# # 补充1:如果是纯英文字符,可以直接加前缀b得到bytes类型
# # l = [
# # b'1111aaa1\n',
# # b'222bb2',
# # b'33eee33'
# # ]
#
# # 补充2:'上'.encode('utf-8') 等同于bytes('上',encoding='utf-8')
# l = [
# bytes('上啊',encoding='utf-8'),
# bytes('冲呀',encoding='utf-8'),
# bytes('小垃圾们',encoding='utf-8'),
# ]
# f.writelines(l)

# flush:不让操作系统攒够一波再写,flush让操作系统立马写!!!!大多数情况下都不要执行,因为操作系统的是优化机制,flush一般测试的时候用
with open(r'db.txt',mode='at',encoding='utf-8') as f:
f.write("我的天:12345")
f.flush() #让操作系统立马写

#了解
with open('db.txt', mode='rt', encoding='utf-8') as f:  #与mode有关
print(f.readable()) #是否可读
print(f.writable()) #是否可写
print(f.encoding) #编码类型
print(f.name) #操作的文件名
 



posted @ 2021-01-29 09:58  欢喜悲  阅读(85)  评论(0)    收藏  举报