网站首页 > java教程 正文
文件读写属于一种常见的IO操作,由于操作系统将底层操作磁盘的接口向上封装为一种通用接口,因此Python中读写文件的基本方法和JAVA、PHP等高级编程语言一样,先请求操作系统打开一个文件描述符,通过操作系统提供的接口从这个文件对象中读取数据,或者把数据写入这个文件中,最后当文件读写操作完成后关闭文件。
需要注意的是文件读写完成后必须及时关闭文件,一方面打开的文件会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限制的,比如Linux操作系统中我们可以使用ulimit -n命令查看最多可打开文件的数量。另一方面在写文件时,操作系统是把数据放到内存缓冲区异步写入磁盘中,并不会立刻把数据全部写入磁盘,而调用close()方法可以使操作系统把没有写入磁盘的数据全部写入磁盘中,防止数据丢失的情况。接下来我们先看下正确的文件打开方式。
文件打开的几种方式
Python内置了open()方法打开了一个文件,如下所示。文件打开模式有'r'、'w'、'a'、'r+'、'w+'、'a+'、'b'等,'r'只读模式打开文件,并将文件指针指向文件头,如果文件不存在会报错;'w'只写模式打开文件,并将文件指针指向文件头,如果文件存在则将其内容清空,不存在则创建;'a'以只追加可写模式打开文件,并将文件指针指向文件尾部,如果文件不存在则创建。对应于open()方法打开文件需要有close()方法关闭文件。
f = open('/mnt/media/log.txt', 'r') f.read() f.close()
由于读写文件时都有可能产生IOError,比如文件不存在的情况,此时open()方法会抛出一个IOError的异常,那么后面的f.close()就不会被调用。为了保证无论是否出错都能正确地关闭文件,我们可以使用try ... finally来实现。
try: f = open('/mnt/media/log.txt', 'r') f.read() finally: if f: f.close()
由于try ... finally方式实现较为繁琐,Python引入了with语句会自动调用f.close()方法,使得代码更简洁。
with open('/mnt/media/log.txt', 'r') as f: f.read()
大文件读取几种方式
对文件的读取操作是将文件中的数据加载到内存中,那么对于大文件的读取,如果一次把文件中全部的内容全部加载到内存中显然会耗尽系统的内容。我们看下Python中读取文件常用的方法read()、readline()、readlines()对于大文件读取的支持情况:read(size)方法是从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止,如果文件比较小,用read()一次读取文件较为方便,但如果不能确定文件大小,反复调用read(size)比较保险;readline()方法每次读出一行内容,所以读取时占用内存小,比较适合大文件。readlines()方法读取整个文件所有行,保存在一个列表list变量中,每行作为一个元素,读取大文件时比较占内存。
说到大文件的读取,有个linecache模块,这里要说明下的是这个模块的优势是通过缓存文件内容的方式来加快下次读取文件的速度,所以需要耗费更多的内存,那么以下是我在Linux发行版LEDE+MT7688的环境下对readlines、linecache.getlines以及遍历文件这三种方式在内存的使用情况下的对比:
count = len(open(filepath, 'r').readlines()) _________________________________________________________ count = = len(linecache.getline(filepath) ) _________________________________________________________ count = 0 for count, line in enumerate(open(filepath,'r')): pass count += 1 ________________________________________________ count = len([ "" for line in open("filename","r")])
不打开文件:Mem: 37648K used, 88184K free, 116K shrd, 0K buff, 12540K cached readlines读取文件:Mem: 69560K used, 56272K free, 124K shrd, 0K buff, 27004K cached linecache.getlines读取文件:Mem: 70396K used, 55436K free, 116K shrd, 0K buff, 26996K cached 遍历方式读取文件:Mem: 53032K used, 72800K free, 116K shrd, 0K buff, 27668K cached
但是linecache.getlines在读取文件的速度上是有绝对优势的,因为文件内容已经缓存在内存中了,下次读取可以直接从内存中获取,可以使用linecache.checkcache检测文件在磁盘上是否发生了变化,如果变化了需要使用linecache.updatecache更新缓存。不过首次读取文件需要打开文件,对于一个15M左右20000行的日志文件三种方式差不多需要8、9秒的时间,但第二次读取文件linecache.getlines方式是微秒级的。
readlines读取文件:
time count 215794 type1 is 9.58759188652
time count 215794 type1 is 1.70862102509
time count 215794 type1 is 2.05462002754
time count 215794 type1 is 1.69754505157
time count 215813 type1 is 2.1633579731
time count 215813 type1 is 1.61879992485
遍历方式读取文件:
time count 215508 type2 is 8.8404238224
time count 215508 type3 is 2.22844409943
time count 215508 type2 is 2.19772100449
time count 215508 type3 is 2.57516384125
time count 215586 type2 is 2.12095785141
time count 215586 type3 is 2.55960321426
time count 215586 type2 is 2.1704659462
time count 215586 type3 is 2.11596107483
linecache.getlines读取文件:
time count 214811 type4 is 8.19337201118
time count 214811 type4 is 6.50882720947e-05
time count 214811 type4 is 9.41753387451e-05
time count 214811 type4 is 6.69956207275e-05
time count 214811 type4 is 9.41753387451e-05
time count 214811 type4 is 6.89029693604e-05
觉得文章还可以的话不妨收藏起来慢慢看,有任何意见或者看法欢迎大家评论!
我是一名python开发工程师,整理了一套python的学习资料,如果你想提升自己,对编程感兴趣,关注我并在后台私信小编:“08”即可免费领取资料!希望对你能有所帮助!
- 上一篇: 正确理解和使用JAVA中的字符串常量池
- 下一篇: Java HeapDump 生成解析
猜你喜欢
- 2024-11-27 大小仅1M的SHP文件读写APP Shapefile over Map
- 2024-11-27 Java内存区域
- 2024-11-27 「深入理解Java虚拟机」第二章 Java内存区域与内存溢出异常
- 2024-11-27 vue上传大文件的解决方案
- 2024-11-27 Springboot+VUE+MiniO来优雅实现文件存储
- 2024-11-27 Tomcat项目内存参数调优
- 2024-11-27 Java应届毕业生应该掌握哪些技能
- 2024-11-27 VUE-超大文件上传-如何上传文件-大文件上传
- 2024-11-27 一个文件占多少内存?看字节
- 2024-11-27 Springboot项目修改文件传输(minio)限制大小
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)