文件操作

文件操作

冯诺依曼体系架构

CPU由运算器和控制器组成

运算器,完成各种算数的运算,逻辑运算,数据传输等数据加工处理

控制器,控制程序的执行

存储器,用于记忆程序的数据,列如内存

输入设备,将数据或者程序输入到计算机中列如键盘 鼠标

输出设备,将数据或者程序的处理结果展示给用户,列如显示器,打印机等等

 

一般说的IO操作,指的是文件的IO,如果是指网络的IO都会直接说网络IO

文件的IO常操作

open—-打开   read—-读取    写入—-write  close—–关闭

readline—行读取   readlines—-多行读取   seek—-文件指针操作   tell—指针位置

打开操作

open(file,mode=’r’,buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None)

打开一个文件,返回一个文件对象和文件的描述符。打开文件失败,则返回异常

基本使用:

创建一个文件test,然后打开它,用完关闭

f = open(‘test’)
print(f.read())
f.close()

文件操作中,最常用的操作就是读写

文件的访问操作的模式有两种:文本模式和二进制模式。不同的模式下,函数的操作不尽相同。表现结果也不一样

open的参数

file 打开或者要创建的文件名,如果指定路径。默认是当前路径

Mode模式

r 缺省的,表示只读打开

w   只写打开

x 创建并写入一个新的文件

a 写入打开,如果文件存在,则追加

b 二进制模式
t 缺省的文本模式

+ 读写打开一个文件,给原来只读只写方式打开提供缺失的读或者写的能力

练习:

#r模式
f = open(‘test’,’r+’)
f.read()
f.write(‘abc’)
f.close()
print(f)

 

f = open(‘test’,’w+’)
f.read()
f.write(‘123’)
f.close()

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

R

只读打开文件,则用write方法会抛异常

如果文件不存在,抛出FileNotFoundError异常

 

W

如果只写方式打开,如果读则抛出异常

如果文件不存在,则直接创建文件

如果文件存在,则清空文件内容

f = open(‘test1′,’x’)
f.write(‘abc’)
f.close()

X

文件不存在则创建文件,并以只读方式打开

文件存在,抛出FileExisError异常

A

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

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

r是只读,wxa都是只写

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

文本模式t

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

二进制模式b

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

f = open(“test”,’rb’)
s = f.read()
print(type(s))
print(s)
f.close()
f = open(‘test’,’wb’)
s = f.write(“马哥教育”.encode())
print(s)
f.close()

 

f = open(“test”,’r+’)
s = f.read()
f.write(“马哥教育”)
print(f.read())
f.close()

 

+

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

文件指针

上面的例子中,已经说明了有一个指针

文件指针,指向当前字节位置

mode=r 指针的起始位置在0

mode=a 指针的起始位置在EOF

tell()显示指针当前的位置

seek(offset[,whence])

移动文件指针位置,offest偏移多少字节,只能是正整数

文本模式下

whence 0 缺省值,表示从头开始,offest只能是正整数

whence 1 表示从当前位置,offest只接受0

whence 2 表示从EOF开始,offest只接受0

文本模式支持从头开始向后偏移的方式

Whence1表示从当前位置开始偏移,但是只支持偏移0,相当于原地不动,所以没什么用

Whence2表示从EOF开始,只支持偏移0,相当于移动文件指针到EOF

Seek是按照字节偏移的

二进制模式下

Whence 0 缺省值,表示从开头开始,offest只能说正整数

Whence 1 表示从当前位置,offest可正可负

Whence 2 表示从EOF开始,offes可正可负

二进制模式支持任意起点的偏移,从头,丛尾,从中间位置开始

向后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’)
print(io.DEFAULT_BUFFER_SIZE)
f.write(“magedu.com”.encode())
f.seek(0)
f.write(“www.magedu.com”.encode())
f.flush()
f.close()

f = open(“test4″,’w+b’,4)
f.write(b”mage”)
f.write(b”du”)
f.close()

文本模式

f = open(“test”,’w+’,1)
f.write(“mag”)
f.write(“magedu”*4)
f.write(‘\n’)
f.write(“hello\npython”)
f.close()

 

import io
f = open(‘test’,”w+”,15)
f.write(“mage”)
f.write(“du”)
f.write(‘hello\n’)
f.write(‘\npython’)
f.write(‘a’*(io.DEFAULT_BUFFER_SIZE – 20))
f.write(“\nwww.magedu.com/python”)

 

Buffering = 0

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

f = open(‘test’,”wb+”,0)
f.write(b’m’)
f.write(b’a’)
f.write(b”g”)
#f.write(b.’magedu*4′)
f.write(b’\n’)
#f.write(b.’hello\npython’)
f.close()

 

Buffering = -1 tb,都是io.DEFAULT_BUFFER_SIZE

Buffering = 0 b关闭缓冲区t不支持

Buffering = 1 b就一个字节,t行缓冲,遇到换行符才flush

Buffering > 1 b模式表示行缓冲值的大小,缓冲区的值可以超过io.DEFAULT_BUFFER_SIZE直到设定的值超过后才把缓冲flust模式,是io.DEFAULT_BUFFER_SIZEflush完成后吧当前字符串也写入磁盘

似乎看起来很麻烦,一般来说,只需要记得:

文本模式,一般都用默认缓冲区大小

二进制模式,是一个个字节的操作,可以指定buffer的大小

一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不能调整它

一般编程中,明确知道需要写磁盘了,都会手动调用榆次flush,而不是等到自动flush或者close的时候

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

None表示缺省编码,依赖于操作系统,Windowslinux测试如下代码

f = open(‘test’,’w’)

f.write(‘啊’)
f.close()

 

Windows下缺省GBK(0xB0A1),LINUX下缺省UTF-8(0xE5 95 8A)

其他参数

Error

什么样的编码将被捕获

Nonestrict表示有编码错误将抛出ValueError异常:ignore表示忽略

Newline

文本模式中,换行的转换,可以转换为None’’空子串,’\r’ , ‘\n’ , ‘\r\n’

读时。None表示’\r’ , ‘\n’ , ‘\r\n’都会被转换为’\n’:表示不会自动转换通用换行符,其他合法字符表示换行符就是指定字符,就会按照指定字符分行

写时,None表示’\n’都会被替换为系统缺省行分隔符os.linesep ‘\n’ 或表示’\n’不替换:其他合法字符表示’\n’会被替换为指定的字符

f = open(‘test’,’w’)
f.write(‘python\rwww.python.org\nwww.magedu.com\r\npython3′)
f.close()

newline = [None,”,’\n’,’\r\n’]
for nl in newline:
f = open(‘test’,’r+’,newline=nl)
print(f.readline())
f.close()

Closefd

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

Read

Size表示读取的多少个字符的字节,负数或者None表示读取到EOF

f = open(‘test’,’r+’,0)
f.write(“magedu”)
f.write(‘\n’)
f.write(‘马哥教育’)
f.seek(0)
f.read(7)
f.close()
f = open(‘test’,’rb+’)
f.read(7)
f.read(1)
f.close()

行读取

Readline(size = -1)

一行行读取文件内容。Size设置一次能读取行内几个字符或字节。

Readline(hint = -1)

读取所有行的列表。指定hint则返回指定的行数

f = open(‘test’)
for line in f:
print(line)

f.close()

Write(s),把子串s写入到文件中并返回字符的个数

Writeline(lines),将字符串列表写入文件

f = open(‘test’,’w+’)
lines = [‘abc’,’123\n’,’magedu’]
f.writelines(lines)
f.seek(0)
print(f.read())
f.close()

Close

Flush并关闭文件对象

文件已经关闭,再次没有任何效果

其他

Seekable()是否可seek

Readable()是否可读

Writeable()是否可写

Closed 是否已经关闭

上下文管理

问题的引出

 

lst = []
for _ in range(2000):
lst.append(open(‘test’))
print(len(lst))

Lsof列出打开的文件,就没有#yum install lsof

$ lsof -p 1427 | grep test | wc -l

Lsof -p 进程号

Ulimit -a 查看所有限制,其中openfile就是打开文件的次数,默认1024

for x in lst:
x.close()

1,异常处理

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

f = open(‘test’)
try:
f.write(‘abc’)#文件只读,写入失败
finally:
f.close()#这个可以

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

2. 上下文管理

一种特殊的语法,交给解释器去释放文件对象

del f
with open(‘test’) as f:
f.write(‘abc’)#文件只读写入失败
f.close()

 

使用with ……as 关键字

上下文的管理的语句块并不会开启新的作用域

With语句块执行完的时候,会关闭文件对象

f = open(‘test’)
with f:
f.write(“abc”)
f.close()

 

对于类似于文件对象的IO对象,一般来说都需要在不使用的时候关闭注销,释放资源

IO被打开的时候,会获取一个文件描述符,计算机的资源是有限的,所以操作系统都会做限制

练习

指定一个源文件,实现copy到目标目录。

filename1 = ‘tmp/test.txt’
filename2 = ‘tmp/test1.txt’

f = open(filename1,’w+’)
lines = [‘abc’,’123′,’namgedu’]
f.writelines(‘\n’.join(lines))
f.seek(0)
print(f.read())
f.close()

def copy(src,dest):
with open(src) as f1:
with open(dest, ‘w’) as f2:
f2.writel(f1.read())

copy(filename1,filename2)

 

有一个文件,对其单词进行统计,不区分大小写,并显示单词重复最多的10个单词

d = {}
with open(‘sample’,encoding=’utf-8′) as f:
for line in f:
words = line.split()
for word in map(str.lower,words)
d[word] = d.get(word,0)+1

print(sorted(d.items(),key=lambda item:item[1],reverse=True)) 

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/97340

联系我们

400-080-6560

在线咨询

工作时间:周一至周五,9:30-18:30,节假日同时也值班

QR code