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分

你可能感兴趣的:(24-python文件IO(一))