python文件操作(一)

一 文件操作介绍

计算机系统分为:硬件系统、软件系统两部分,软件系统又可以分为系统软件和应用软件。

        我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,但是,应用程序是无法直接操作硬件的,需要通过操作系统来完成。操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来。

       这样的话,我们只需要关注操作文件的流程就行了,也就是:

1.打开文件,得到文件句柄并赋值给一个变量

2.通过句柄对文件进行操作

3.关闭文件

二 python实现流程

      根据上面的流程,在python中我们是这样实现的:

#1. 打开文件,得到文件句柄并赋值给一个变量
f=open('a.txt','r',encoding='utf-8') #默认打开模式就为r,也就是读文件

#2. 通过句柄对文件进行操作
data=f.read()

#3. 关闭文件
f.close()

      现在我们可以分析一下第一步,操作系统和应用程序是怎么交互的:

1.由应用程序向操作系统发起系统调用open()

2.操作系统打开该文件,并返回一个文件句柄给应用程序

3.应用程序将文件句柄赋值给变量f

注意事项:

1.千万记得操作完文件后要写f.close()。从上面的交互流程我们可以看到,打开一个文件是包含两部分资源的:操作系统级打开的文件+应用程序的变量。在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:

1、f.close() #回收操作系统级打开的文件
2、del f #回收应用程序级的变量

其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,

而python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们,在操作完毕文件后,一定要记住f.close()

但还是经常有人会忘记加上,所以还有一种方式打开文件,并且不用你写close,就是通过with来管理上下文:

with open('a.txt','w') as f:
    data = f.read()
 
with open('a.txt','r') as read_f,open('b.txt','w') as write_f:
    data=read_f.read()
    write_f.write(data)

#第二种格式通过逗号分开,可以在一行打开两个文件

2.建议指定编码。有时候大家打开文件,发现拿到的数据都是乱码的,这是因为f=open(...)是由操作系统打开文件,那么如果我们没有为open指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。若要保证不乱码,文件以什么方式存的,就要以什么方式打开。
f=open('a.txt','r',encoding='utf-8')

三 打开文件的模式

从上文我们知道:文件句柄 = open('文件路径', '模式'),模式可以是以下方式以及他们之间的组合:

Character Meaning
‘r' open for reading (default)
‘w' open for writing, truncating the file first
‘a' open for writing, appending to the end of the file if it exists
‘b' binary mode
‘t' text mode (default)
‘+' open a disk file for updating (reading and writing)
‘U' universal newline mode (for backwards compatibility; should not be used in new code)
 
   

我们逐个举例说明:

'r'模式,只读模式【默认模式,文件必须存在,不存在则抛出异常】,所以我们首先要有一个文件,我这里文件叫'陈粒',内容如下:

11111111
222222222
333
4444
555
555
6666
555
6666

'r'模式操作如下:

f=open('陈粒',encoding='utf-8')
data=f.read()
print(data)
f.close()
View Code

这样我们拿到的文件所有的内容,那我们要一行行的读,就要用到readline()方法:

f=open('陈粒','r',encoding='utf-8')
print(f.readable())
print('第1行',f.readline())
print('第2行',f.readline())
print('第3行',f.readline())
View Code

结果是:

True
第1行 
第2行 
第3行 
        我们用了3个readline(),读取的是前3行的内容,说明readline()在读取一行内容后,光标移动到下一行首部。光标是什么,我们写文件的时候,一直会有一个光标在最后闪烁,我们读取文件的时候,是从光标的位置开始读的(光标是默认在0位置上的,后面会讲一个移动光标的方法叫seek)。
       如果我想要里面任意一行,比如最后一行的内容,上面的方法就很难做到了,这时候需要用到readlines()方法:
 
f=open('陈粒','r',encoding='utf-8')
data=f.readlines()
print(data)
print(data[-1])
f.close()
View Code

结果是:

['11111111\n', '222222222\n', '333\n', '4444\n', '555\n', '555\n', '6666\n', '555\n', '6666\n']
6666

       可以看到readlines()拿到的是所有结果,但是按行放在一个列表里面,通过列表索引,我们可以拿到任何一行的内容。

'w'模式:只写模式【不可读;不存在则创建;存在则清空内容】,可以自己创建,那就简单了,直接来:

 

f=open('陈粒1','w',encoding='utf8')
f.write('11111111\n')
f.write('222222222\n')
f.write('333\n4444\n555\n')
f.close()
View Code

       运行之后你会发现,多了一个文件叫“陈粒1”,里面就是我们写入的内容:

 

11111111
222222222
333
4444
555

         可见我们可以写一行,加上换行符就可以写多行,那除了write()方法,还有别的方法可以写吗?当然是有的,比如writelines(),和我们的readlines()感觉对应,所以里面的内容也要是一个列表:

 

f=open('陈粒1','w',encoding='utf8')
f.write('11111111\n')
f.write('222222222\n')
f.write('333\n4444\n555\n')
f.writelines(['555\n','6666\n'])
f.close()
View Code

       再看我们的文件,又多了两行。下面再看一段代码:

 

f=open('陈粒1','w',encoding='utf8')
f.write('11111111\n')
f.write('222222222\n')
f.write('333\n4444\n555\n')
f.writelines(['555\n','6666\n'])
f.writelines(['555\n','6666\n',1]) # 文件内容只能是字符串,只能写字符串
f.close()
View Code

       运行之后发现报错了,因为我们最后写入了一个数字,而文件的内容都是字符串,所以写也都是写入字符串的,不能写数字,当然其他类型也是不可以的。

'a'追加写模式【不可读;不存在则创建;存在则只追加内容】,看到我们上面的w模式,写在同一个文件里面,会把之前的覆盖,那么如果只想在文件里面加点东西,显然需要另一种模式,就是a模式:

 

f=open('陈粒1','a',encoding='utf-8')
f.write('写到文件最后')
View Code

       这时候看结果,最后已经加上一行了:

 

11111111
222222222
333
4444
555
555
6666
555
6666
写到文件最后

       上面说的3种模式非常简单,也是我们常用的3种模式,但都只是单一的模式,很多时候我们需要同时对一个文件进行读写操作,就需要这三个配合'+'一起使用了:

 

"+" 表示可以同时读写某个文件
r+, 读写【可读,可写】
w+,写读【可读,可写】
a+, 写读【可读,可写】

        在说这三个模式之前,需要了解一个知识点就是:文件没有修改这一说,大家所认知的修改文件,是应用程序为了方便使用写的一个功能,改是在内存中改,但最终还是覆盖硬盘中的源文件,所以修改文件本质上是覆盖之前的文件。所以我们看看'r+'模式:

 

f = open('陈粒1','r+',encoding='utf-8')
data = f.read()
print(data)
# f.write('aaa')
f.close()
View Code

       从结果看到,读文件是没有问题的,现在把写的那一行取消注释,看看文件内容:

 

11111111
222222222
333
4444
555
555
6666
555
6666
写到文件最后aaa

       不会换行写,如果你要换行写,就要在aaa前面加上\n,那单独写是什么情况:

 

f = open('陈粒1','r+',encoding='utf-8')
# data = f.read()
# print(data)
f.write('aaa')
# f.write('\naaa')
f.close()
View Code

      结果是:

 

aaa11111
222222222
333
4444
555
555
6666
555
6666
写到文件最后

      覆盖了前面三个111,因为光标默认是0,而写是从光标处开始写的,所以导致覆盖,这几种模式理解就行,用到不多。那如果我们要修改文件怎么办?就要打开两个文件了:

 

r_f = open('陈粒1','r',encoding='utf-8')
data = r_f.readlines()
r_f.close()

w_f = open('陈粒2','w',encoding='utf-8')
data.pop(2)
w_f.writelines(data)
w_f.close()
View Code

     一个文件读,一个文件写,写之前把读到的数据列表删除了一个元素,所以’陈粒2‘文件就少了一行333,这样就实现了文件修改啦。有人说这样拿到的是新文件,但我想要在原来的文件修改怎么办?那就在改完之后把源文件删除后,再把新文件rename一下就好了,os模块能搞定这个需求。下一篇要讲的是二进制方式打开文件。

 

 

posted @ 2019-05-06 11:51  彭方炎QAQ  阅读(419)  评论(0编辑  收藏  举报