文件管理

文件操作
冯诺依曼体系架构
在这里插入图片描述
CPU由运算器和控制器组成

  • 运算器,完成各种算数运算 逻辑运算 数据传输等数据加工处理
  • 控制器,控制计算机各部件协调运行
  • 存储器,用于记忆程序和数据,例如内存
  • 输入设备,将数据或者程序输入到计算机中,例如键盘鼠标
  • 输出设备,将数据或程序的处理结果展示给用户,例如显示器 打印机等
    一般的IO操作,值得是文件IO,如果指的是网络IO,都会直接说网路IO

文件IO操作

columncolumn
open打开
read读取
write写入
close关闭
readline行读取
readlines多行读取
seek文件指针操作
tell指针位置

打开操作
open(file,mode=‘r’,buffering=-1,encoding=None,errors=None,newline,closefd=Tue,opener=None)
打开一个文件,返回一个文件对象(流对象)和文件描述符.打开文件失败,则返回异常
创建一个文件,然后打开它,用完关闭

f = open("test")  #file对象  
#windows<_io.TextIOWrapper name='test' mode='r' encoding='cp936'>
#linux <_io.TextIOWrapper name='test' mode='r' encoding='UTF-8'>
print(f.read) #读取文件
f.close() #关闭文件

文件操作中,最常用的就是读和写
文本访问的模式有两种:文本模式和二进制模式.不同模式下,操作函数不尽相同,表现的结果也不一样
注:windows中使用codepage代码页,可以认为每一个代码页就是一张编码表.cp936等同于GBK

open
open默认是只读模式r打开已经存在的文件

r模式

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

w模式

  • 表示只写方式打开,如果读取则抛出异常
  • 表示文件不存在,则直接创建文件
  • 表示文件存在,则清空文件内容

x模式

  • 文件不存在,创建文件,并只写方式打开
  • 文件存在,抛出FileNotFoundError异常

a模式

  • 文件存在,只写打开,追加内容

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

  • r是只读,wxa都是只写.

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

文本模式t
字节流,将文件的字节按照某种字符编码理解,按照字符操作.open的默认mode就是rt

二进制模式b
字节流,将文件就按照字节理解,与字符编码无关.二进制模式操作时,字节操作使用bytes类型

+模式

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

文件指针
文件指针,指向当前字节位置
mode = r,指针其实在0
mode = a,指针起始在EOF
tell()显示指针当前位置
seek(offset[,whence])
移动文件指针位置.offset偏移多少字节,whence从哪里开始

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

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

buffering:缓冲区
-1表示使用缺省大小的buffer.如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值,默认是4096或者8192.
如果是文本模式,如果是终端设备,是行缓存方式,如果不是,则使用二进制模式的策略

  • 0,只在二进制模式使用,表示关buffer
  • 1,只在文本模式使用,表示使用行缓冲.意思就是见到换行符就flush
  • 大于1,用于指定buffer的大小

buffer 缓冲区
缓冲区一个内存空间,一般来说是一个FIFO队列,到缓冲区满了或者达到闸值,数据才会flush到磁盘
flush()将缓冲区数据写入磁盘
close()关闭前会调用flush()
io.DEFAULT_BUFFER_SIZE缺省缓冲区大小,字节

二进制模式

import io 
f = open('test','w+b',4)
print(io.DEFAULT_BUFFER_SIZE)
f.write("hello".encode())
#cat test
f.seek(0)
f.flush()
f.close()

文本模式

buffering=1,使用行缓冲
f = open('test','w+',1)  
f.write("hello") #cat test
f.close()


buffering>1,使用指定大小的缓冲区  
f = open('test','w+',8)  
f.write("hello") #cat test
f.close()

buffering = 0
这是一种特殊的二进制模式,不需要内存的buffer,可以看做是一个FIFO的文件

f = open('test','wb+',0)  
f.write("h") #cat test
f.write("h") #cat test
f.write("h") #cat test
f.close()

总结:

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

encoding:编码,仅文本模式使用
None 表示使用缺省编码,依赖操作系统.Windows Linux下测试如下代码
Windows下缺省GBK(0xB0A1),linux下缺省UTF-8(0xE5 95 8A)

其他参数
什么样的编码错误将被捕捉
None和strct表示有编码错误将抛出ValueError异常;ignore表示忽略

newline
文本模式中,换行的转换.可以为None “空串” ‘\r’ ‘\n’ ‘\r\n’
读时,None表示’\r’ ‘\n’ ‘\r\n’ 都被转换为’\n’;“表示不会自动转换通用换行符;其他合法字符表示换行符就是指定字符,就会按照指定字符分行
写时,None表示’\n’都会被替换为系统缺省行分割符os.linesep;’\n’或”’\n’不替换;其他合法字符表示’\n’会被替换为指定的字符

newlines = [None,'','\n','\r\n']
for i in newlines:
    f = open("test",'r+',newline = i)
    print(f.readlines)
    f.close()
#运行结果
['mnmn\n', '123\n', 'abc\n', '789']
['mnmn\r\n', '123\r\n', 'abc\r\n', '789']
['mnmn\r\n', '123\r\n', 'abc\r\n', '789']
['mnmn\r\n', '123\r\n', 'abc\r\n', '789']

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

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

f = open('test','r+')
f.write('a')
f.seek(0)
f.read(1)
f.close()

#二进制  
f = open('test','rb+')
f.read(1)
f.close()

行读取
readline(size=-1)
一行行读取文件内容.size设置一次能读取行内几个字符或字节
readlines(hiht=-1)
读取所有行的列表.指定hiht则返回指定的行数

f = open('test')
for line in f:
    peint(line.encode())

f.close()

write
write(s),把字符串s写入到文件中并返回字符的个数
writelines(lines),将字符串列表写入文件

f = open('test')
lines = ['abc','123\n','hello']
f.writelines(lines)
f.seek(0)
print(f.read())
f.close()

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

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

上下文管理
问题的引出
在Linux中,执行

lst = []
for _ in range(2000):
    lst.append(open('test'))

print(len(lst))

lsof列出打开的文件.没有就 yum install lsof

$ ps aux | grep python
$ lsof -p 9255 | grep test | wc -1
$ ulimit -a

ps 命令返回进程,grep出python进程ID
lsof -p 进程号,列出该进程的所有文件描述符,grep出test文件文件描述符,wc统计
ulimit -a 查看所有限制.其中open files就是打开文件数的限制,默认1024

1 异常处理
当出现异常的时候,拦截异常.但是,因为很多代码都可能出现OSError异常,还不好判断一床就是应为资源限制产生的

f = open('test')
try:
    f.write("abc") #文件只读,写入失败
finally:
    f.close() # 这样才行  

使用finally可以保证打开的文件被关闭

2 上下文管理
一种特殊的语法,交给解释器去释放文件对象

def f
with open('test') as f:
    f.write("abc") #文件只读
# 测试f是否关闭
f.closed #f的作用域

上下文管理

  1. 使用with…as关键字
  2. 上下文管理的语句并不会开启新的作用域
  3. with语句执行完的时候,会自动关闭文件对象
f1 = open('test')
with f1:
    f1.write("abc") #文件只读,写入失败 

f1.closed

对于类似于文件对象的IO对象,一般来说都不需要在不使用的时候关闭,注销,以释放资源
IO被打开的时候,会获得一个文件描述符.计算机资源是有限的,所以操作系统都会做限制,就是为了保护计算机的资源不要被完全耗尽,计算资源是共享的,不是独占的
一般情况下,除非特别明确的知道资源情况,否则不要提高资源的限制值来解决问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值