第十五天python3 文件IO(一)
一、文件打开
open(path,flag[,encoding][,errors])
参数说明:
path:要打开文件的路径
flag:打开方式(
r:以只读的方式打开文件,文件的描述符放在文件开头
rb:以二进制格式只读的方式打开文件,文件的描述符放在文件开头
r+:打开一个文件用于读写,文件描述符放在文件的开头
w:打开一个文件只用于写入,文件的描述符放在文件的开头,如果该文件已经存在会覆盖,如果不存在则创建新文件
wb:打开一个文件只用于写入二进制,如果该文件会覆盖,如果该文件不存在新创建文件
w+:打开一个文件用于读写,如果该文件存在会覆盖,如果该文件不存在新创建文件
a:打开一个文件用于追加,如果文件存在文件描述符将会被放到文件末尾
a+:打开一个文件用于追加)
encoding:编码方式
errors:错误处理
errors="ignore" 忽略错误
二、文件指针
seek(offset[,whence]) 移动文件指针位置,offest偏移多少字节,whence从哪里开始;
mode=r(只读) 指针其实位置在0
mode=a(追加 ) 指针其实在EOF
tell() 显示指针当前位置
文本模式下:
whence 0 缺省值,表示从头开始,offest只能接受正整数;
whence 1 表示从当前位置;offset只接受0;
whence 2 表示从EOF开始,offset只接受0;
示例:
f = open('test',r+)
f.write('abcdefg')
此时指针在末尾,当f.read()读的时候是没有数据的;
f.seek(3) 表示偏移3个字节,f.read()的结果为defg;
当f.seek(0),指针到开头时,再去f.read()的时候就可以读取到数据了;
f.seek(0,1),表示指针回到末尾;
whence只接受0,1,2三个参数;
中文示例:
f = open('test',r+)
f.write('北京欢迎你')
测试:
在mac中运行:
f.seek(2)
f.read()
会报错,UnicodeDecodeError;f.seek(3)则不报错,在mac系统中,一个中文占3个字节;
在windows中运行:
f.seek()
f.read()
不会报错,在windows系统中,一个中文占2个字节;
二进制模式下:
whence 0 缺省值,表示从头开始,offset只能是正整数
whence 1 表示从当前位置开始,offset可正可负;
whence 2 表示从EOF开始,offset可正可负;
f=open('test','rb+')
f.write('abcdef')
示例:
f.seek(-3,2) 从文件末尾开始向左偏移3,得到的结果为def;
二进制模式下支持任意起点的偏移,从头,从尾,从中间位置开始;
向后seek可以超界,但是向前seek的时候,不能超界,否则抛异常;
三、buffer缓冲区
-1表示使用缺省大小的buffer,如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值,默认是4096或者8192(字节);如果是文本模式,如果是终端设备,是行缓存的方式,如果不是,则使用二进制模式的策略;
0 只在二进制模式中使用,表示关闭buffer;
1 只在文本模式中使用,表示使用行缓冲,意思就是见到换行符就flush;
1< 大于1用于指定buffer的大小;
缓冲一般是一个队列;缓存一般是字典的方式存储;
缓冲区是一个内存空间,一般来说是FIFO(先进先出)队列,到缓冲区满了或者达到阈值,数据才会flush到磁盘;
flush() 将缓冲区数据写入磁盘;
close() 关闭前会调用flush()
示例:
f = open('test','w+')
f.write('!'*1024)
这时候分两种情况:
1、当执行一次写操作,再执行一次seek,或者tell或者read的时候,指针都会发生变化,因此会进行一次flush,将缓冲区的内容写入磁盘,cat test就可以看到内容;
2、当只执行写操作,不做seek、read、tell操作,这时候写的内容在缓冲区,没有写入磁盘,因此cat test是看不到内容的;当我连续执行了9次写操作,再去cat test的时候发现可以看到内容了,这是>因为,默认缓冲区8192字节(8K)写满溢出了,做了一次flush;
import io
print(io.DEFAULT_BUFFER_SIZE)。查看默认缓冲区大小;
在文本模式中,f = open('test','w+',4),指定buffer大小为4,似乎不起作用,依然用的是系统默认的buffer_size;
示例2:
在二进制模式中关闭buffer;
f = open('test','wb+',0) #0表示在二进制模式中关闭buffer
f.write(b'!'*1024)
此时的效果就是,不写buffer,立即写磁盘;
总结:
1、文本模式中,一般都用默认缓冲区大小;
2、二进制模式,是一个个字节的操作,可以指定buffer的大小;
3、一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它;
4、一般编程中,明确知道要写磁盘了,都会手动调用一次flush,而不是等到自动flush或者close的时候;
encoding:编码,仅文本模式使用
windows下缺省GBK(0xBOA1),linux下缺省UTF-8(0xE5 95 8A)
四、其他参数
newline
该参数用来指定读取时,对换行符的处理;文本模式中,换行的转换,可以为None,空串,\r、\n、\r\n;
mac的换行符是\r;Linux的换行符是\n;windows的换行符是\r\n;
读取文件时:
测试文件的换行符都是\r\n;
情况1:缺省为None,表示通用换行符“\n”,即文件换行符是啥,读出来都是“\n”;
当读取文件时,所有的\r都被替换成了\n;
情况2:newline = "",表示读取的换行符保持不变;
情况3:newline="\n",newline="\r",表示换行符就是指定字符,就会按照指定的字符分行;执行效果跟情况2一样;
文件写入时:
情况1:缺省值为None;写入的"\n"自动变为系统默认的换行符;写入“\n”,用notepad++打开发现被替换成了系统默认的换行符;
情况2:newline="" 和 newline="\n",表示不做任何转换写入;
情况3:newline="\r" 表示将“\n”、“\r”都当做“\r”写入;
os.linesep
查看操作系统默认的换行符
read
read(size=-1)
size表示读取的多少个字符或者字节,负数或者None表示读取到EOF;
行读取
readline(size=-1)
一行一行读取文件内容,size设置一次能读取行内几个字符或者字节;
readlines(hint=-1)
读取所有行的列表,指定hint则返回指定的行数;
示例:
读取文件内容的时候,可以不用readlines;可以直接迭代;
f = open('test','r+')
for line in f:
print(line)
write
write(s) 把字符串s写入到文件中并返回字符的个数;
writelines(lines) 将字符串列表写入文件;
close
释放文件描述符,并关闭文件对象;
其他
seekable() 是否可seek
readable() 是否可读
writeable() 是否可写
closed 是否已经关闭
上下文管理
问题的引出,在Linux中执行:
# -*- coding: utf-8 -*-
lst = []
for _ in range(2000):
lst.append(open('test'))
print(len(lst))
在Linux下执行该python脚本,发现会报错,“OSError: [Errno 24] Too many open files: 'test'”;这是因为打开的文件数过多,超过了系统定义的最大文件打开数;
可以用ulimit -n查看系统的最大文件打开数;
由此,这种只打开,不关闭的情况,会导致系统的最大文件打开数耗尽;为了避免这种情况的发生,python提供了上下文管理,它会在程序运行结束后,自动关闭文件;
with
一种特殊语法,交给解释器去释放文件对象;
写法1:
with open('test') as f:
f.write('abcdefg')
with语句块执行完成后,会自动关闭文件对象;
写法2:
f = open('test','w+')
with f:
f.write('abcdefg')
#f.write(str(1/0)) 抛异常,验证在抛异常情况下,是否能关闭文件,f.closed 查看是否关闭;
第十五天python3 文件IO(一)的更多相关文章
- python系列十四:Python3 文件
#!/usr/bin/python #Python3 文件 from urllib import requestimport pprint,pickle'''读和写文件open() 将会返回一个 fi ...
- 第十六天python3 文件IO(二)
BytesIO操作 io模块中的类 from io import BytesIO 内存中,开辟的一个二进制模式的buffer,可以像文件对象一样操作它: 当close方法被调用的时候,这个buffer ...
- 第四十五篇--将文件写入SD卡
RAM: 运行内存 ROM: 外部存储,手机内部存储 SD卡:外部存储,SD卡存储. 在存储文件时千万不要忘记向清单文件中添加相应权限,并且android6.0以后还要添加运行时权限 还有一个权限有所 ...
- Unity3D学习笔记(二十五):文件操作
文件是什么? 存储在硬盘上的最后的节点. 文件夹是什么? 文件的上级单位称为文件夹. 文件夹的基本结构? 文件夹是层级化结构的,对于同级的文件夹不可以重名,父文件夹和子文件夹可以同名> IO:I ...
- python系列十五:Python3 错误和异常
#!/usr/bin/python #-*-coding:gbk-*- #Python3 错误和异常'''Python 语法错误或者称之为解析错语法分析器指出了出错的一行,并且在最先找到的错误的位置标 ...
- Linux上天之路(十五)之文件查找
主要内容 精确查找 模糊查找 1. 精确查找 find - search for files in a directory hierarchy 递归地在层次目录中处理文件 查找方式: 按文件属性查找 ...
- 第十七天python3 文件IO(三)
CSV文件 csv是一个被行分隔符.列分隔符化分成行和列的文本文件: csv不指定字符编码: 行分隔符为\r\n,最后一行可以没有换行符: 列分隔符常为逗号或者制表符: 每一行称为一条记录record ...
- Python学习笔记(二十五)操作文件和目录
摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014319253241 ...
- TestNG(十五)xml文件实现多线程测试
package com.course.testng.thread; import org.testng.annotations.Test; public class ThreadOnXml { @Te ...
随机推荐
- 关于transform属性的一些理解
3D transform transform进行动画演示时,是以元素的中心为基准点的,可以使用transform-origin改变元素转变的基准点. 所有的transform动作改变都会引起X.Y轴的 ...
- hooks 与 animejs
hooks 与 animejs 本文写于 2020 年 1 月 13 日 animejs 是现如今非常不错的一个 js 动画库.我们将其与 React Hooks 融合,使它更方便的在 React 中 ...
- CSS基础学习(二)
11.CSS背景 ①设置背景颜色(颜色值通常可以用十六进制(如#000000)或者颜色名称(如red)来表示) 属性:background-color 例: body { background-col ...
- python目录索引
python目录索引 python基础数据类型1 目录 part1 part2 运算符 格式化 part3 字符串 字符串常用操作方法 part4 列表 列表的创建: 列表的索引,切片 列表的增删改查 ...
- CenterNet训练时黑白图片不能画框的问题
解决CenterNet在detect.py中不能画框的问题 在第centernet.py的第198行的中加上这一行 image = image.convert('RGB')
- vue新手入门之使用vue框架搭建用户登录注册案例,手动搭建webpack+Vue项目(附源码,图文详解,亲测有效)
前言 本篇随笔主要写了手动搭建一个webpack+Vue项目,掌握相关loader的安装与使用,包括css-loader.style-loader.vue-loader.url-loader.sass ...
- 从零开始学YC-Framework之鉴权
一.YC-Framework鉴权是基于哪一个开源框架做的? YC-Framework鉴权主要基于Dromara开源社区组织下的Sa-Token. 1.什么是Sa-Token? Sa-Token是一个轻 ...
- Kubernetes client-go DeltaFIFO 源码分析
概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...
- AT32F415 修改时钟和晶振方法(原创)
1. 简介 我们几乎是国内第一批使用AT32F415芯片的客户,那个时候芯片还没涨价,岁月一切静好.使用AT32F415 做了几个小产品,也在持续出货.后来大家都知道,涨价缺货愈演愈烈.好在我们提前囤 ...
- C++ 获取指定的重载函数地址
刚刚看到一篇博客,说 std::bind 无法绑定正确的重载函数.这里的问题并不是 std::bind 能力不足,而是将函数名传递给 std::bind 时编译器无法取到这个函数的地址(也就是符号,编 ...