python文件操作

在讲io操作的时候,先回忆一下冯诺依曼体系的计算机组成,分为五大构造,输入设备,存储器,输出设备,运算器和控制器。运算器和控制器合起来就是cpu。所有的数据都要先加载到内存。内存要多用,O要少用,要知道数据是在内存中怎么玩的,才能提高效率。

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

控制器:控制程序的执行

存储器:用于记忆程序和数据,例如内存。

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

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

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

使用Python来读写文件是一件非常简单的操作,使用open()函数来打开一个文件,获取到一个文件句柄,然后通过文件句柄就可以进行各种各样的操作。当然根据打开方式的不同能够执行的操作也会有响应的差异。

文件IO常用操作包括:open(打开),read(读取),write(写入),close(关闭),readline(行读取),Readlines(多行读取),seek(文件指针操作),tell(指针位置)
而打开文件的方式:r,w,a,r+,w+,a+,rb,wb,ab,r+b,w+b,a+b,默认使用的是r(只读)模式。只读(r,rb),只写(w,wb),追加(a,ab)而+是读原模式的补充。

打开操作

open(file,mode="r",buffering = -1,encoding = None,errors=None,newline = None,closefd = True,opener = True),这个函数是打开一个文件,然后返回一个文件对象(流对象)和文件描述符。打开文件失败的话,则返回异常。前面四个参数经常使用。

在liunux中,一切皆文件,所以打开的不仅仅是我们所说的文件。

基本的使用:

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

f = open("test.txt") #先在当前工作文件路径下创建一个txt文件,不能忘记了文件后面的txt,不然会出错。file对象。

#windows<_io.TextIOWrapper name = "test" mode = "r" encoding= "cp936">#cp936可以认为是gbk.
#Linux<_io.TextIOWrapper name = "test" mode = "r" encoding= "UTF-8">#所以window的程序直接在Linux下运行,不注意编码会出错。
#中文中,常用的字符编码有gb2312,gbk,gbk可以认为是超集,而gb2312可以认为是子集。window默认是gbk编码。
print(f.read())#读取文件
f.close()#关闭文件

结果为:
abcbde
bde

文件操作中,最常用的操作就是读和写,文件访问的模式有两种,一种文本模式,一种二进制模式,不同模式下,操作函数不尽相同,表现的结果也不一样。

open函数的参数

file:打开或者是要创建的文件名,如果不指定路径的话,默认就是当前路径。这个时候需要明白绝对路径和相对路径。file也可以是一个文件描述符(012)。

绝对路径就是从磁盘根目录开始一直到文件名,而相对路径则是同一个文件夹下的文件,相对于当前这个程序所在的文件夹而言,如果在同一个文件夹中,则相对路径就是这个文件名,如果在上一层文件夹,则要../

 

 文件操作推荐使用相对路径,这样把程序拷走的时候,直接把项目拷走就能直接运行。

encoding表示编码集. 根据文件的实际保存编码进行获取数据, 一般来说,更多的是多的是utf-8.但是应该注意的是,rb读取出来的数据是bytes类型,所以在rb模式下,不能选择encoding字符集。不然会报错。

f = open("test1.txt",mode = "rb",encoding = "utf-8")
print(f.read())
f.close()

结果为:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-216-de94656245a0> in <module>
----> 1 f = open("test1.txt",mode = "rb",encoding = "utf-8")
      2 print(f.read())
      3 f.close()

ValueError: binary mode doesn't take an encoding argument


f = open("test1.txt",mode = "rb")
print(f.read())
f.close()

结果为:
b'xpc'

rb的作用是在读取非文本文件的时候有用,比如读取mp3、图像、视频等信息的时候需要用到。因为这种数据是没办法直接显示出来的。

mode

mode模式分为很多种:

  1. r(只读模式,它是缺省的,默认就是只读打开),open默认的就是只读模式r打开已经存在的文件,如果使用了write方法,会抛异常。如果文件不存在的话,也会抛异常,抛出的是filenotfounderror异常。
  2. w,表示只写打开,如果读取的话则会抛异常,如果文件不存在的话,则直接创建文件,如果文件存在,则清空文件内容。
  3. x,文件不存在的话,创建文件,并只写模式打开,而如果文件存在的话,则会抛出fileexistserror错误。
  4. a,文件存在,只写打开,然后追加内容。而如果文件不存在的话,则创建后,只写打开,追加内容。
  5. b,二进制模式,字节流,它是将文件按照字节理解,与字符编码无关,二进制模式操作时,字节操作使用bytes类型。
  6. t,缺省的,文本模式。它是字符流,将文件的字节按照某种字符编码理解,按照字符来操作,默认就是rt。
  7. +,读写打开一个文件,给原来只读,只写方式打开缺失的读或者写能力。

上面的那个例子中,可以看到默认是文本打开模式,且是只读的。

f = open("test.txt") 
print(f.read())#读取文件
f.write("abc")#只读模式下,写入的话,就会报错。
f.close()#关闭文件

结果为:

abcbde
bde
---------------------------------------------------------------------------
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-45-224cc7b51825> in <module>
      1 f = open("test.txt")
      2 print(f.read())#读取文件
----> 3 f.write("abc")
      4 f.close()#关闭文件

UnsupportedOperation: not writable

而在只写模式下读取,也会报错。

f = open("test.txt",mode = "w") 
print(f.read())
f.close()

结果为:
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-48-ebbae1182d79> in <module>
      1 f = open("test.txt",mode = "w")
----> 2 print(f.read())
      3 f.close()

UnsupportedOperation: not readable

在w模式下,如果文件不存在,则直接创建文件,如下:

f = open("test1.txt",mode = "w") 
f.write("abcnd")#创建并写如新的内容
f.close()

f = open("test1.txt",mode = "r") #读取前面创建的内容
a = f.read()
print(a)
f.close()

结果为:

abcnd

在w模式下,如果文件存在,则会清空文件内容。

f = open("test.txt",mode = "r") #读取内容
a = f.read()
print(a)
f.close()

f = open("test.txt",mode = "w") 
f.write("hahahaha")#创建并写如新的内容
f.close()

f = open("test.txt",mode = "r") #读取内容
a = f.read()
print(a)
f.close()

结果为:

1234567890
hahahaha

要是只写打开已经存在的文件,不做任何操作,文件里面的内容也会被清空。

f = open("test.txt",mode = "r") #读取内容
a = f.read()
print(a)
f.close()

f = open("test.txt",mode = "w") 
f.close()

f = open("test.txt",mode = "r") #读取内容,内容为空。
a = f.read()
print(a)
f.close()

结果为:
hahahaha
f = open("test.txt",mode = "x") #文件已存在,报错
a = f.read()
print(a)
f.close()

结果为:
---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
<ipython-input-64-73ddf96bc2ce> in <module>
----> 1 f = open("test.txt",mode = "x") #文件已存在,报错
      2 a = f.read()
      3 print(a)
      4 f.close()

FileExistsError: [Errno 17] File exists: 'test.txt'

上面的例子可以看到,x模式下打开一个已经存在的文件,会抛异常。而不存在,创建后,只能是只写模式打开。读的话出错。

f = open("test2.txt",mode = "x") #文件不存存在,创建
a = f.read()
print(a)
f.close()

结果为:

---------------------------------------------------------------------------
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-65-610a021c0d76> in <module>
      1 f = open("test2.txt",mode = "x") #文件不可读
----> 2 a = f.read()
      3 print(a)
      4 f.close()

UnsupportedOperation: not readable
f = open("test4.txt",mode = "x") #文件不存存在,创建
f.write("abcdefg")
f.close()


f = open("test4.txt",mode = "r") #读取内容,内容为上面创建的内容。
a = f.read()
print(a)
f.close()

结果为:
abcdefg

在a模式下,如果文件存在的话,只写打开然后在后面追加内容。如果读的话,会报错。

f = open("test1.txt",mode = "r")
a = f.read()
print(a)
f.close()

f = open("test1.txt",mode = "a")
f.write("hahahahha")
f.close()

f = open("test1.txt",mode = "r")
a = f.read()
print(a)
f.close()

结果为:
abcnd
abcndhahahahha

而在a模式下,如果文件不存在,则创建后,只写打开,追交内容。

f = open("test5.txt",mode = "a")
f.write("hahahahha")
f.close()

f = open("test5.txt",mode = "r")
a = f.read()
print(a)
f.close()

结果为:

hahahahha

由上面的例子可以看到,r是只读,而w、x、a都是只写,而且wxa都可以产生新文件,w不管文件存在与否,都会生成全新的内容的文件,a不管文件是否存在,都能在打开的文件尾部追加,而x必须要求文件事先不存在,自己创建一个新文件。

f = open("test5.txt",mode = "rb")
s = f.read()
print(type(s))#bytes
print(s)
f.close()

结果为:
<class 'bytes'>
b'hahahahhahahahahha'

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

f = open("test5.txt",mode = "rb")
s = f.read()
print(type(s))#bytes
print(s)
f.close()

#encode() 方法以 encoding 指定的编码格式编码字符串。
#用法:str.encode(encoding='UTF-8',errors='strict')
f = open("test5.txt",mode = "wb")
s = f.write("许鹏".encode())#返回了两个字符的字节数6
print(s)
f.close()

f = open("test5.txt",mode = "rb")
s = f.read()
print(type(s))#bytes
print(s)
f.close()

结果为:

<class 'bytes'>
b'123456'
6
<class 'bytes'>
b'\xe8\xae\xb8\xe9\xb9\x8f'

encode默认是按照utf-8进行编码的。也可以直接在前面加一个b。

print("许鹏程".encode())
"许鹏程".encode("utf-8")

结果为:

b'\xe8\xae\xb8\xe9\xb9\x8f\xe7\xa8\x8b'
b'\xe8\xae\xb8\xe9\xb9\x8f\xe7\xa8\x8b'

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

f = open("test1.txt",mode = "r+",encoding = "utf-8")
s= f.read()
print(s)
f.write("")
print(f.read())#文件指针在写到了最后,所以什么都读不出来。
f.close()

f = open("test1.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

结果为:

abcndhahahahhabacbac哈哈

abcndhahahahhabacbac哈哈哈
f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

f = open("test.txt",mode = "r+",encoding = "utf-8")
f.write("")
print(f.read())
f.close()

f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

结果为:
12345
12345
哈12345
 
f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

f = open("test.txt",mode = "w+",encoding = "utf-8")
f.write("")
print(f.read())
f.close()

f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

结果为:
哈12345

哈
f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

f = open("test.txt",mode = "a+",encoding = "utf-8")
f.write("wangbadan")
print(f.read())#文件指针在最后,所以读不出来什么。
f.close()

f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

结果为:

哈

哈wangbadan
f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

f = open("test.txt",mode = "x+",encoding = "utf-8")
f.write("wangbadan")
print(f.read())#文件指针在最后,所以读不出来什么。
f.close()

f = open("test.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

结果为:
哈wangbadanwangbadan
---------------------------------------------------------------------------
FileExistsError                           Traceback (most recent call last)
<ipython-input-141-f7b6cdaceca5> in <module>
      4 f.close()
      5 
----> 6 f = open("test.txt",mode = "x+",encoding = "utf-8")
      7 f.write("wangbadan")
      8 print(f.read())#文件指针在最后,所以读不出来什么。

FileExistsError: [Errno 17] File exists: 'test.txt'
f = open("test7.txt",mode = "x+",encoding = "utf-8")#文件不存在,创建
f.write("wangbadan")
f.close()

f = open("test7.txt",mode = "r",encoding = "utf-8")
s= f.read()
print(s)
f.close()

结果为:
wangbadan

上面的例子,可以说明存在一个文件指针。

文件指针

mode = r的时候,指针的起始位置为0,mode = a的时候,文件指针在EOF结束的位置。

tell()显示指针当前的位置(应该特别注意很多时候在前面写入的话,是覆盖,这样改变了源文件,不好。),seek(offset,whence)则是移动文件指针的位置,offset表示偏移多少个字节。whence表示从哪里开始。很多时候中文用seek不太好。

在文本模式下,whence 0 是缺省值,表示从头开始,offset只能是正整数。比如seek(0)表示从开始位置向右偏移0,也就是还是起始位置,seek(2)也就是从开始位置向右偏移2个字符。这个用的最多。

whence1表示从当前位置,offset只接受0.

whence2表示从EOF开始,offset只接受0。

#有问题
f = open("test1.txt",mode = "r",encoding = "utf-8")
print(f.read())
f.close()

f = open("test1.txt",mode = "r+",encoding = "utf-8")
f.tell()#起始位置
print(f.read())#指针移动到最后

f.tell()#指针已经到结束位置了。
f.seek(0)#指针移动到起始位置
print(f.read())

f.seek(2,0)#文件从起始位置偏移2个字节
print(f.read())#读取从2个字节到最后的字节。

f.seek(2,1)#offset必须为0
f.seek(2,2)#offset必须为0
f.close()

结果为:
许鹏
许鹏
许鹏
 
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-4-7b08f2458cbd> in <module>
     12 
     13 f.seek(2,0)#文件从起始位置偏移2个字节
---> 14 print(f.read())#读取从2个字节到最后的字节。
     15 
     16 f.seek(2,1)#offset必须为0

f:\Anaconda3\lib\codecs.py in decode(self, input, final)
    320         # decode input (taking the buffer into account)
    321         data = self.buffer + input
--> 322         (result, consumed) = self._buffer_decode(data, self.errors, final)
    323         # keep undecoded input until the next call
    324         self.buffer = data[consumed:]

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb8 in position 0: invalid start byte
#中文
f = open("test2.txt",mode = "r",encoding = "utf-8")
print(f.read())
f.close()

f = open("test2.txt",mode = "w+",encoding = "utf-8")
f.write("许鹏大坏蛋")
f.tell()#文件指针到最后了,
print(f.read())#指针移动到最后,读不到了
f.close()

f = open("test2.txt",mode = "r+",encoding = "utf-8")
print(f.read(3))#从头开始读三个字符
f.seek(3)#从开始位置向右移3个字节
print(f.tell())
print(f.read())
f.seek(3)#f.seek(3)
print(f.read())
f.close()

结果为:
许鹏大坏蛋

许鹏大
3
鹏大坏蛋
鹏大坏蛋

所以在文本模式下,支持从开始位置向后偏移的方式,whence为1表示从当前位置开始偏移,但是只支持偏移0,相当于原地不动,所以没什么用,whence为2表示从eof开始,只支持偏移0,相当于移动文件指针到EOF。

而在二进制模式下,whence 0 缺省值,表示从头开始,offset只能是正整数。

whence 1 表示从当前位置开始,offset可正可负。

whence2 表示从eof开始,offset可正可负。

f = open("test3.txt",mode = "r",encoding = "utf-8")
print(f.read())
f.close()

f = open("test3.txt",mode = "rb+")
f.tell()#文件指针在开始位置
print(f.read())#从头开始读

f.tell()#文件指针到最后了
f.write(b"abc")
f.seek(0)#起始
print(f.read())#从头开始读

f.seek(0)
f.seek(2,1)#从当前指针开始,向后2
print(f.read())

f.seek(-2,1)#从当前指针开始,向前2
print(f.read())

f.seek(2,2)#从eof开始,向后2
print(f.read())

f.seek(-2,2)#从eof开始,向前2
f.read()
print(f.read())


f.close()

结果为:

许鹏大坏蛋abc
b'\xef\xbb\xbf\xe8\xae\xb8\xe9\xb9\x8f\xe5\xa4\xa7\xe5\x9d\x8f\xe8\x9b\x8babc'
b'\xef\xbb\xbf\xe8\xae\xb8\xe9\xb9\x8f\xe5\xa4\xa7\xe5\x9d\x8f\xe8\x9b\x8babcabc'
b'\xbf\xe8\xae\xb8\xe9\xb9\x8f\xe5\xa4\xa7\xe5\x9d\x8f\xe8\x9b\x8babcabc'
b'bc'
b''
b''

所以,二进制模式支持任意起点的偏移,从头,从尾,从中间位置开始。向后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("test10.txt","w+b")#w+b表示二进制下的写读操作
print(io.DEFAULT_BUFFER_SIZE)
f.write("xpc.zs".encode())

f.seek(0)
f.write("abcd".encode())#覆盖了前面的xpc.
print(f.read())

f.flush()
f.seek(0)
print(f.read())
f.close()

结果为:
8192
b'zs'
b'abcdzs'
#有些问题
import
io f = open("test11.txt",mode = "w+b",buffering= 5)#二进制模式下的写读操作 print(io.DEFAULT_BUFFER_SIZE) f.write(b"xpc.zs") print(f.read()) f.flush() f.seek(0) print(f.read()) f.close() 结果为: 8192 b'' b'xpc.zs'

文本模式下当buffering= 1的时候,使用的是行缓冲,设置成大于1的时候,一般都没有什么用处。因为在jupyter中,例子没有试验成功。但是在命令环境下可以。

 

 上面的打开文件,然后写入,每次写入,都在jupyter中读,直到最后写入了一个换行符,jupyter才读出来,也就是换行的时候才刷新一次,写入磁盘。如下图。

 

buffering = 0这是一种特殊的二进制模式,不需要内存的buffering,可以看做是一个fifo的文件。在交互命令下,如下图,每写一个,不刷新,直接读都可以。写一个就可以读一个。

 

 所以,buffering = -1,不管是t,还是b,缓冲大小都是默认值。

buffering = 0,b是关闭缓冲区,t不支持。

buffering = 1,b就是一个字节,t则是行缓冲,遇到换行符才flush.

buffering >1,b模式下表示行缓冲大小,缓冲区的值可以超过io.DEFAULT_BUFFER_SIZE,直到设定的值超出后才把缓冲区flush。t模式下,是io.DEFAULT_BUFFER_SIZE,flush完后把当前字符串也写入磁盘。

似乎看起来很麻烦,一般来说,记住以下几点就好了。

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

encoding

编码代表的是怎么来理解二进制,是一个字节一个字节的来,还是几个字节几个字节的来。none表示使用缺省编码,这依赖于操作系统,window下默认是gbk,linux默认是utf-8,utf-8是Unicode的网络传输码,gbk和utf-8类似于映射关系,他们不是一一对应的。一个中文utf—8一般来说占用3个字节,但并不是绝对的。有时候会有4个。ASCII码常用的要记住。

其他参数

errors:什么样的 编码错误将被捕获,none和strict表示有编码错误将被抛valueerror错误,ignore表示忽略。

newline:文本模式中,换行的转换,可以为none,“,’“\r”,"\n","\r\n",读的时候none表示前面的都被转换为“\n”,"(空字符串)表示不会自动转换通用换行符,其他合法字符表示换行符就是指定字符,就会按照指定字符分行。

写时,none表示"\n"都会被替换为系统缺省行分隔符os.linesep,"\n"或”表示“\n”不替换,其他合法字符表示"\n"会被替换为指定的字符。

closefd:关闭文件描述符,true表示关闭它,false会在文件关闭后保持这个描述符。fileobj.fileno()查看。文件描述符有缓存,关闭了再看,还是那个文件描述符,文件描述符是唯一对应到文件的。

read()方法

read(siez = -1)表示读取的多少个字符或者字节,当里面的值为负数或者None时,则表示读到结尾。

f= open(file= "zss",encoding = "utf-8",mode = "w+")
f.write("xpc-xpc-xpc-xpc")
f.write("\n")
f.write("zss")
f.seek(0)
print(f.read(7))#读七个字符
f.seek(0)
print(f.read(-1))#读到结尾

f.seek(0)
print(f.read())#读到结尾

f.close()

结果为:

xpc-xpc
xpc-xpc-xpc-xpc
zss
xpc-xpc-xpc-xpc
zss


#二进制模式
f = open(file = "xpc",mode = "wb+")
f.write("许鹏xpcxpcxpc".encode())
f.seek(0)
print(f.read(6))
f.seek(0)
print(f.read(-1))
f.seek(0)
print(f.read())
f.close()

结果为:
b'\xe8\xae\xb8\xe9\xb9\x8f'
b'\xe8\xae\xb8\xe9\xb9\x8fxpcxpcxpc'
b'\xe8\xae\xb8\xe9\xb9\x8fxpcxpcxpc'

所以read()是将文件中的所有内容全部读取出来,这样有弊端,如果文件过大,很容易崩溃。而read(n)表示读取几个字节或字符,当需要再次读取的时候,指针会从当前位置继续去读,而不是从头开始,也就是要看文件指针的位置。

行读取

readline(size=-1)表示一行行读取文件内容,size设置一次能读取行内几个字符或字节。

readlines(hint=-1)读取所有行的列表,也就是将每一行形成一个元素,放入列表,返回的是个列表。指定hint则返回指定的行数。

f = open(file = "abc.txt",mode = "r")
print(f.readline())#中间空了一行,是因为本身有换行符,然后print默认一个换行符,要去掉的话,可以用strip去掉一个。
print(f.readline().strip())
print(f.readline(5))#读取第三行的前5个字符

f.seek(0)
print(f.readlines())


f.seek(0)
print(f.readlines(2))#这里设置几都只有第一行?
f.close()

结果为:

xpc.zs

123444
asjaw
['xpc.zs\n', '123444\n', 'asjawdfoafma\n', "sfaw'pawkaw\\\n", "waw'fdawkf\\aw\n"]
['xpc.zs\n']

文件句柄还是一个可迭代对象,可以一行行迭代。

#按行迭代
f = open(file = "abc.txt",mode = "r")#返回可迭代对象
for i in f:
    print(i.strip())
    
f.close()

结果为:

xpc.zs
123444
asjawdfoafma
sfaw'pawkaw\
waw'fdawkf\aw

write

write(s),是把字符串s写入到文件中并返回字符的个数。而writelines(lines),是将字符串列表写入文件中。写的时候要注意编码。

f = open(file = "abc.txt",mode = "w+")
lines = ["abc","123\n","abc"]#提供换行符
f.writelines(lines)
f.seek(0)
print(f.read())
f.close()

结果为:
abc123
abc

close

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

其他的操作

seekable()是否可seek

readable()是否可读

writable()是否可写

closed是否已经关闭。

上下文管理

上下文管理是一种特殊的语法,当打开文件后,不需要自己去关闭,交给解释器去释放文件对象。它使用with……as关键字,同时,上下文管理的语句块并不会开启新的作用域,而当with语句块执行完的时候,会自动关闭文件对象。

 with open("test.txt") as f:
        f.write("abc")

结果为:

---------------------------------------------------------------------------
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-3-5e8b5c83866d> in <module>
      1 with open("test.txt") as f:
----> 2        f.write("abc")
      3 f.closed

UnsupportedOperation: not writable

f.closed
结果为:
true

上面的例子可以看到,使用上下文管理语法,当出现错误,抛异常后,文件没有关闭的情况下,解释器自动帮助我们关闭了。

它还有另外的一种写法。

f1 = open("test1.txt",mode = "r")
with f1:
    f1.write("abc")

结果为:
---------------------------------------------------------------------------
UnsupportedOperation                      Traceback (most recent call last)
<ipython-input-5-40ef8ccf9294> in <module>
      1 f1 = open("test1.txt",mode = "r")
      2 with f1:
----> 3     f1.write("abc")

UnsupportedOperation: not writable

f1.closed
结果为:
true

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

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

with open("test",mode = "w+",encoding = "utf-8") as f:
    lines = ["xpc","pxc","line"]
    f.writelines("\n".join(lines))
    f.seek(0)
    print(f.read())

结果为:

xpc
pxc
line

def copyfile(src,dest):
    with open(src) as f1:
        with open(dest,"w") as f2:
            f2.write(f1.read())
            
filename = "test1"
filename = "test2"
copyfile(filename1,filenae2)

结果为:

 

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

 

 

posted on 2019-12-10 17:09  xpc199151  阅读(419)  评论(0编辑  收藏  举报

导航