24-python文件IO(一)

01-上章题目讲解:在上一章节里

02-open方法和模式

文件操作:非常重要

冯诺依曼体系架构


image.png

内存:掉电易失
CPU由运算器和控制器组成:

  • 运算器,完成各种算数运算,逻辑运算,数据传输等数据加工处理
  • 控制器,控制程序执行
  • 存储器,用于记忆程序和数据,例如内存
  • 输入设备,将数据或者程序输入到计算机中,例如键盘,鼠标
  • 输出设备,将数据或程序的处理结果展示给用户,例如显示器,打印机等
    一般说IO操作,指的是文件IO,如果指的是网络IO,都会直接说网络IO
    机械磁盘上存的都是二进制,且存储的数据未必是连续的,所以叫机械硬盘也叫随机访问设备。

文件IO常用操作

image.png

打开操作

文件系统是靠目录管理,文件一定是放在目录下的;windows和linux文件系统不一样;windows系统是带逻辑驱动器,逻辑驱动器有自己的根,因为有逻辑驱动器,所以要加盘符;linux是根文件系统。


image.png

f = open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True,opener=None)
打开一个文件,返回一个文件操作对象(流对象)和文件描述符。打开文件失败,则返回异常。打开后一定要关闭。
基本使用:
创建一个文件test,然后打开它,用完关闭

image.png

其中的encoding='cp936',cp936的cp代表codepage,等于gbk编码;windows默认编码是gbk,linux这是UTF-8;gbk编码中文是2字节;UTF-8 编码常见中文是3个字节;GBK兼容GB2312编码,但比GB2312包含了更多的汉字:中文存储时,第一个字节码值在127256之间,第二个字节码值在0256之间。
Ipython环境下运行shell命令(前提是linux系统装的有ipython,这样在ipython环境下运行shell命令时才可以),需要在命令前加 ! ,例如 !ls
文件访问的模式有2种:文本模式(字符访问,与编码有关)和二进制模式(字节流访问,不管编码)。不同模式下,操作函数不尽相同,表现的结果也不一样。

open的参数

mode模式

image.png
r read

只读打开文件,如果使用write方法会抛异常。
如果文件不存在,抛出FileNotFoundError异常

w write

表示只写方式打开,如果读取则抛出异常
如果文件不存在,则直接创建文件
如果文件存在,则清空文件内容
w:没有的话创建,有的话直接覆盖
f = open('test','w')
f.close
以上两行可以创建一个空文件


image.png

print后 会返回写进去的字符数量

x create

文件不存在直接创建,并只写方式打开
文件已存在,会抛FileExistsError异常

a append

文件存在,只写打开,追加内容
文件不存在,则创建后,只写打开,追加内容。

总结以上几种模式

r是只读,wxa都是只写。
wxa都可以产生新的文件,w不管文件存在与否,都会生成全新内容的文件;a不管文件是否存在,都能在打开的文件尾部追加;x必须要求文件事先不存在,自己造一个新文件。

文本模式t:操作单位是字符

字符流,将文件的字节按照某种字符编码理解,按照字符操作。open的默认mode是rt

二进制模式b:

字节流,将文件按照字节理解,与字符编码无关。二进制模式操作时,字节操作使用bytes类型
一个文件读取的编码方式要和写入时的编码方式一致,否则读取时会出现乱码。
二进制操作写入中文到文件中:

f = open('test3','wb')
#f.write('啊')  #TypeError: a bytes-like object is required, not 'str' 需要像bytes一样的东西,不要字符串
#f.write(b'啊') #bytes can only contain ASCII literal characters  只认ASII,这样写不行
f.write('啊'.encode('gbk')) #encode 默认编码方式为 utf-8. 啊 用utf-8编码占3个字节:b'\xe5\x95\x8a'  汉字的正确编码方式为gbk
f.close()

f = open('test3','r',encoding='gbk')
print(f.read())
f.close()

一般来讲,各种编码都兼容ASII码
各种编码都是二进制字节流去根据各自编码表对应不同的字符;二进制字节流本身都是ASII码。

+

+ 为r,w,a,x提供缺失的读写功能,但是,获取文件对象依旧按照r,w,a,x自己的特征。
+ 不能单独使用,可以认为它是为前面的模式字符做增强功能。

03-文件指针

文件指针:指向当前字节位置
mode=r,指针起始位置在0
mpde=a,指针起始位置在EOF
tell()显示指针当前位置
seek(offset[,whence]):移动指针位置。offset偏移多少字节,whence从哪里开始。
tell()和seek()都是针对字节的偏移,所以用他们处理字符流有风险

文本模式下:

  • whence 0 缺省值,表示从头开始,offset只能接受0和正整数
  • whence 1 表示从当前位置,offset只接受0,相当于原地不动,所以没什么用
  • whence 2 表示EOF开始,offset只接受0,相当于移动文件指针到EOF。
  • seek是按照字节偏移的。
  • 文本模式下只支持从开头向后偏移的方式

二进制模式下

  • whence 0缺省值,表示从头开始,offset只能是正整数,包括0
  • whence 1表示从当前位置,offset可正可负
  • whence 2表示从EOF开始,offset可正可负
  • 二进制模式支持任意起点的偏移,从头,从尾,从中间位置开始。
  • 向后seek可以超界,但是向前seek的时候,不能超界,否则会抛异常。

linux 下删除一个文件的原理是将该文件的inode扔出去,让别的文件使用,从而覆盖掉改文件。
inode:索引节点,它用来存放档案及目录的基本信息,包含时间、档名、使用者及群组等。
04-缓冲区原理
缓存和缓冲的区别:
缓存:数据结构为dict,目的是快速找到想要的内容
缓冲:数据结构为list,一堆数据排队放在那

04-缓冲区原理

buffering:缓冲区

  • open的一个参数
  • -1 表示使用缺省大小的buffer。
    • 如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值,默认是4096或者8192,目前多是8192 个字节。
    • 如果是文本模式:
      • 如果是终端设备,是 行缓存方式
      • 如果不是,则使用二进制模式的策略。
  • 0 只在二进制模式使用,表示关闭buffer,即不需要内存buffer,可以看做是一个FIFO的文件。
  • 1 只在文本模式使用,表示使用行缓冲。意思是见到换行符就flush
  • 大于1 用于指定buffer的大小;但是在文本模式下,通过实验发现还是在用buffer的默认值。

buffer缓冲区

缓冲区是内存中的一个连续的空间,一般来说是一个FIFO(先进先出)队列(不支持中间插入,只支持两头操作),到缓冲区满了或者达到阈值,数据才会flush到磁盘。
内存的运行速度比I/O设备高的多
flush()将缓冲区的数据写入磁盘
close()关闭前会调用flush()
内存的东西不是能直接写到磁盘上去的,从内存空间的用户空间,搬到操作系的内核空间,从内核空间写到磁盘缓冲区里,由磁盘缓冲区写入磁盘

buffering 总结

image.png

一般说来只需记得:

  • 文本模式,一般都用默认缓冲区大小
  • 二进制模式,是一个个字节的操作,可以指定buffer的大小
  • 一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它。
  • 一般编程中,明确知道需要写磁盘了,都会手动调用一次flush(f.flash()),而不是等到自动flush或者close的时候。

05-编码描述符及读写方法

encoding:编码,仅文本模式使用

None表示使用缺省编码,依赖操作系统,windows下缺省GBK,linux下缺省UTF-8
UTF-8:用多个字节编码世界上的所有文字;大多数中文落在3个字节上
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码,又称万国码。
GBK:单字节+双字节。ASCII单字节,中文双字节;CODEPAGE=936 ,代表GBK

image.png

跨平台的时候建议用UTF-8
GBK和UTF-8之间编码不一致,需要查表

其他参数

errors

什么样的编码错误将被捕获
None和strict表示编码错误将抛出ValueError异常;ignore表示忽略。
一般都用默认,不用管。

newline

文本模式中换行的转换。可以为None,"空串、'\r'、'\n'、'\r\n'
读时,None表示'\r'、'\n'、'\r\n'都被转换为'\n'
写时,None表示'\n'都会被替换为系统却省行分隔符os.linesep;

f = open("D:/magedu/test",'w')
f.write('py\rwww\nmaedu\r\npython3')
f.close()

newlines = [None,'','\n','\r\n']
for nl in newlines:
    f = open("D:/magedu/test",'r+',newline=nl)
    #print(f.readlines())
    print(f.read().encode()) #通过编码可以将换行符保留,而不是直接去做换行
    f.close()

closefd

关闭文件描述符,True表示关闭它。False会在文件关闭后保持这个描述符。
fileobject.fileno()查看。

f = open("D:/magedu/test",'w')
print(f.fileno())  #文件描述符

文件打开时就会产生一个文件对象。

read

read(size=-1)
size表示读取的多少个字符或字节;负数或者None表示读取到EOF

f = open("D:/magedu/test",'w')
f.write('python\r\n123\r\npython3')
f.close()

f = open("D:/magedu/test",'r+')
print(f.read().encode()) #指针到最后
f.seek(0)  #文件指针回到开头
print(f.readline(1).encode()) #一个个字符读
f.close()

#以后读取文件的每一行可以按照如下的读,可以少写一行
f = open("D:/magedu/test",'r')
for line in f:
    print(line)

write

write(s),把字符串s写入到文件中并返回字符的个数;常用
writelines(lines),将字符串列表写入文件
要自己提供换行符

close

flush并关闭文件对象
文件已经关闭,再次关闭没有任何效果

其他

seekable() :是否可seek
readable():是否可读
writable():是否可写
closed 是否已经关闭

f = open("D:/magedu/test",'r')
print(f.seekable())  # True
print(f.readable()) # True
print(f.writable()) # False
print(f.closed)    # False
for line in f:
    print(line)
f.close()
print(f.closed)  # True

06-上下文管理

问题的引出

在linux中执行如下代码:

lst = []
for _ in range(2000):
    lst.append(open('test')) 
#OSError:[Errorno 24] Too many open files:'test'
print(len(list))

lsof 列出打开的文件。没有就 # yum install lsof
$lsof -p 1427|grep test|wc -l
lsof -p 进程号
ulimit -a 查看所有限制。其中open files 就是打开文件数的限制,默认1024

15分
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容