Python小白学习之路(二十)—【打开文件的模式二】【文件的其他操作】
打开文件的模式(二)
对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作
(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb: 以字节方式读文件
wb: 以字节方式写文件
ab: 以字节方式追加文件
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,所以不能指定编码
1. rb
#错误举例
f = open ('test1.py', 'rb', encoding = 'utf -8')
data = f.read()
print(data)
f.close() #执行结果:
报错
f = open ('test1.py', 'rb', encoding = 'utf-8')
ValueError: binary mode doesn't take an encoding argument (以b方式打开时,因为读取到的内容是字节类型,所以不能指定编码方式,否则会报错)
#正确
f = open ('test1.py', 'rb')
data = f.read()
print(data)
f.close() #执行结果:
b"'hello'\r\n'\xe5\xb0\x8f\xe7\x81\xab\xe9\x94\x85'\r\n'666'"
test1.py中的内容如下:
'hello'
'小火锅'
'666'
分析该程序执行结果:
1. python在windows操作系统下,换行符为在windows操作系统下,换行符为 \r\n
2. ‘字符串’-------encode-------》bytes
bytes---------decode-------》‘字符串’
所以,我们想让执行结果为字符串,可在print时做decode处理
f = open ('test1.py', 'rb')
data = f.read()
print(data.decode('utf-8'))
f.close()
#执行结果:
'hello'
'小火锅'
''
2. wb
#错误举例
f = open ('test1.py', 'wb')
f.write('hello')
f.close()
#执行结果:
TypeError: a bytes-like object is required, not 'str'
(以b方式写入时需要提供字节类型,所以不能写入字符串类型)
#正确
f = open ('test1.py', 'wb')
f.write(bytes('hello\n小火锅', encoding = 'utf-8' ))
f.close()
3. ab
#举例
f = open ('test1.py', 'ab')
f.write(bytes('hello\n小火锅\n', encoding = 'utf-8' ))
f.close()
关于文件的其他操作介绍
1. .encoding 读取文件打开时后的编码方式(即open时指定的编码方式)
#举例
f = open ('test1.py', 'w', encoding = 'GB2312')
f.close()
print(f.encoding)
#执行结果:
GB2312
2. .closed 确定文件是否关闭
#举例
f = open ('test1.py', 'w', encoding = 'utf-8')
f.close()
print(f.closed)
#执行结果:
True
3. .flush 刷新操作(将文件内容从内存刷到硬盘)
4. .tell 读取光标所在位置
补充:文件内光标移动
一: read(3):
1. 文件打开方式为文本模式时,代表读取3个字符
2. 文件打开方式为b模式时,代表读取3个字节
二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate
test1中的内容
aaa
小火锅
666
#举例
f = open ('test1.py', 'r', encoding = 'utf-8')
print(f.tell())
f.readline()
print(f.tell())
f.readline()
print(f.tell())
f.close() #执行结果:
0
5
16
#结果分析:
第一个tell判断光标位置时候,光标在文件开头,即在位置0
读取了一行之后,光标跑到文件第二行开头,但是在Windows操作系统,换行符为 \r\n,占两个字节,而且tell光标移动以字节为单位,所以光标位置为 5
读取了第二行之后,光标跑到了文件第三行开头,光标经历了三个汉字和换行符,在编码方式为 utf-8 时,走过了3*3+2=11个字节,所以光标位置为 16
5. .seek 控制光标的移动
#举例
f = open ('test1.py', 'r', encoding = 'utf-8')
f.seek(2) #光标从默认位置0开始,往后移动两个字节
data = f.read()
print(data) #打印光标后的内容
f.close() #执行结果:
a
小火锅
666
如果,我将test1.py的内容改为
小火锅
aaa
666
再次执行上述程序
#报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8f in position 0: invalid start byte
原因:一个汉字在utf-8编码方式为3个字节,seek(2)移动两个字节,难道有神奇的功能将汉字劈开嘛,所以肯定会报错啊!
关于seek的一些补充:
seek有三种模式,分别为
- 0模式 默认从0开始(不用指定)
- 1模式 从上次相对位置开始
- 2模式 从文件末尾开始seek(第一个参数需要为负数)
举例:
f = open ('test1.py', 'r', encoding = 'utf-8')
f.seek(3)
print(f.tell())
f.seek(9)
print(f.tell())
f.close() #执行结果
3
9
f = open ('test1.py', 'rb')
f.seek(3,1)
print(f.tell())
f.seek(10,1)
print(f.tell())
f.close()
#执行结果
3
13
f = open ('test1.py', 'rb')
f.seek(-3,2) #seek 在模式 2 时,第一个参数为负数
print(f.tell())
print(f.read())
f.close()
#执行结果
18
b'6\r\n'
任务:应用:打开一个日志文件,并且读取最新日志(核心:倒着读文件内容)
日志文件内容如下:
2018/11/20 aaa 上网听歌
2018/11/20 bbb 上网网购
2018/11/20 ccc 上网学习
#方法一
f = open('日志文件', 'rb')
data = f.readlines() #将日志文件的内容以列表形式读到内存中
print(data[-1].decode('utf-8')) #以切片方式读取列表中最后一个元素,即文件最后一行内容 #执行结果
2018/11/20 ccc 上网学习
#方法二
f = open('日志文件', 'rb')
for i in f: #文件循环方式
offs = -10 #设置初始偏移量
while True: #设置一个死循环来读取文件的最后一行内容,读取到break
f.seek(offs, 2) #seek模式2,光标倒着移动
data = f.readlines() #以列表形式读取光标后的内容
if len(data) > 1: #如果该列表长度大于1,说明光标移动到最后一行之前,最后一行内容已被读出,break,反则最后一行内容还未全部读出,将偏移量扩大,直到独处最后一行全部内容
print('文件最后一行:%s'%(data[-1].decode('utf-8')))
break
offs *= 2 #执行结果
文件最后一行:2018/11/20 ccc 上网学习
方法一看着简单,但是方法一需要将日志文件的内容一列表形式全部读到内存中,占用较多内存
方法二的思想就是我用最后一行内容,我倒着读,只关注我想得到的信息
6. .truncate 截取文件内容(实质为文件内容的改写,所以在 open 文件时,需要设置正确的打开文件的模式)
举例:
f = open('日志文件', 'r+',encoding = 'utf-8')
data = f.truncate(8)
print(data)
注意:
- 打开方式不可以是r(报错,实质为文件的改写)
- 打开方式不可以是w w+(这两个模式将内容全部删除,所以截取不到任何内容)
Python小白学习之路(二十)—【打开文件的模式二】【文件的其他操作】的更多相关文章
- Python小白学习之路(十九)—【文件操作步骤】【文件操作模式】
一.文件操作步骤 step1:打开文件,得到文件句柄并赋值给一个变量step2:通过句柄对文件进行操作step3:关闭文件 举例: a = open('hello world', 'r', encod ...
- Python小白学习之路(十二)—【前向引用】【风湿理论】
前向引用 风湿理论(函数即变量) 理论总是很抽象,我个人理解: 代码从上到下执行,一旦遇到定义的函数体,内存便为其开辟空间,并用该函数的名字作为一个标识但是该函数体内具体是什么内容,这个时候并不着急去 ...
- Python小白学习之路(十)—【函数】【函数返回值】【函数参数】
写在前面: 昨天早睡之后,感觉今天已经恢复了百分之八十的样子 又是活力满满的小伙郭 今日份鸡汤: 我始终相信,在这个世界上,一定有另一个自己,在做着我不敢做的事,在过着我想过的生活.-------宫崎 ...
- Python小白学习之路(十五)—【map()函数】【filter()函数】【reduce()函数】
一.map()函数 map()是 Python 内置的高阶函数 有两个参数,第一个是接收一个函数 f(匿名函数或者自定义函数都OK啦):第二个参数是一个 可迭代对象 功能是通过把函数 f 依次作用在 ...
- Python小白学习之路(十八)—【内置函数三】
一.对象操作 help() 功能:返回目标对象的帮助信息 举例: print(help(input)) #执行结果 Help on built-in function input in module ...
- Python小白学习之路(十四)—【作用域】【匿名函数】【编程方法论】【高阶函数】
吧啦吧啦内心戏 在没有具体学作用域之前,我在之前的学习笔记中就有提到 我开始以为是自己自创的词儿 没想到这个词早已经存在(手动捂脸) 真是个无知的小火锅(不知者无罪) 我发现自己最擅长做的事情,就是给 ...
- Python小白学习之路(十六)—【内置函数一】
将68个内置函数按照其功能分为了10类,分别是: 数学运算(7个) abs() divmod() max() min() pow() round() sum() 类型转换(24个) bo ...
- FastAPI 学习之路(十八)表单与文件
系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...
- Python小白学习之路(二十二)—【生成器】
一.什么是生成器? 生成器可以理解成是一种数据类型,特殊地是生成器可以自动实现迭代器协议其他的数据类型需要调用自己内置的__iter__方法所以换种说法,生成器就是可迭代对象 !回忆:很重要的迭代器协 ...
随机推荐
- 转载hibernate 的3种 状态 。。
转自 http://huangtut.iteye.com/blog/261520 对我有帮助,所以收藏了 Hibernate三种状态的区分,以及save,update,saveOrUpdate,m ...
- jar 包 的用处 ,dozer、poi、itext 、jxl 、jbarcode 、itextrenderer jquery 效果
1.dozer 做类型转换的, 新建 xml 文件 描述两个实体的对应关系 ,DozerBeanMapper mapper =new DozerBeanMapper().addMappingFiles ...
- css长度
在CSS样式表中,长度单位分两种: 相对长度单位,如px, em等绝对长度单位,如pt,mm等 CSS相对长度单位(relative length unit) CSS相对长度单位中的相对二字,表明了其 ...
- 简明PR教程
注意:本文供培训使用且仅为第一版 作者也不打算继续更新 本篇文章最早是在为内部培训时所编写的文章 有些疏漏且没有进行校正等工作 我尽力用最简单通俗的语言给大家介绍PR的使用方法 简明PR教程 1.编辑 ...
- const与预处理宏#define的区别
在c语言程序设计时,预处理器可以不受限制地建立宏并用它来替代值.因为预处理器只做一些文本替换,宏没有类型检测概念,也没有类型检测功能.所以预处理器的值替换会出现一些小的问题,出现的这些问题,在c++中 ...
- [转载红鱼儿]Delphi XE7 update1进步太大了
写以下的文字是怀着无比兴奋的心情写的,急于同朋友们分享XE7的进步! 1.更新的bug列表并不全 通过bug修正列表及发布的消息,可以看到up1修正了很多bug,正如我所说,有些bug并没有写到发布的 ...
- 2018.08.30 游戏(概率dp)
题目描述 Alice 和 Bob 两个人正在玩一个游戏,游戏有很多种任务,难度为 p 的任务(p是正整数),有 1/(2^p) 的概率完成并得到 2^(p-1) 分,如果完成不了,得 0 分.一开始每 ...
- springcloud-eureka简单实现
请参考 spring+cloud为服务实战 第三章 一.创建Eureka服务 1.使用Idea创建一个项目 结构如下: 2.pom.xml配置: <?xml version="1.0& ...
- spring3 hibernate4整合后无法查询数据库
spring3和hibernate4整合后无法查询数据库,一方面是因为已经spring3中没有对hibernate4 HibernateTemplate的支持,另外一个就是需要在hibernate的配 ...
- 201709015工作日记--上下文的理解,ASM
1.Android上下文理解 Android上下文对象,在Context中封装一个所谓的“语境”,Activity.Service.Application都继承自Context,所以在这三者创建时都会 ...