一.python中的基本文件方法:


open()方法:

python open() 方法用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写
参数说明:

  • file: 必需,文件路径(相对或者绝对路径)。
  • mode: 可选,文件打开模式
  • buffering: 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
  • encoding: 一般使用utf8
  • mode 参数有:模式描述如下图
    在这里插入图片描述
    'r’模式打开的文件创建的对象只能用read函数读取文件的内容,‘w’模式打开的文件又只能往里写内容。"w+"和"r+"则可以对文件进行读写操作。w+:如果文件存在则先清空文件,如果文件不存在则创建。r+:打开一个文件用于读写。

read([size]):

size :未指定则返回整个文件中的内容,如果文件大小 >2 倍内存则有问题,f.read()读到文件尾时返回""(空字串)。

readlines([size]) :

返回包含size行的列表, size 未指定则返回全部行。

write(str):

如果要写入字符串以外的数据,先将他转换为字符串。

tell():

返回一个整数,表示当前文件指针的位置(就是到文件头的字节数)。

seek(偏移量,[起始位置]):

用来移动文件指针。
偏移量: 单位为字节,可正可负
起始位置: 0 - 文件头, 默认值; 1 - 当前位置; 2 - 文件尾

truncate()

用于截断文件,如果指定了可选参数 size,则表示从文件起始位置截断文件为 size 个字符。 如果没有指定 size,则从当前位置截断;删除该位置后面的所有字符。
原文件内容:

12345

fp = open(r"test.txt", "a+")#打开后文件指针在文件末尾位置
print(fp.tell())
fp.truncate(2)
print(fp.tell())

最终文件内容:

12

输出结果:

5
5

可以看出truncate()方法保留了前两个元素,并且对文件指针没有影响。


fp = open(r"test.txt", "a+")#打开后文件指针在文件末尾位置
fp.seek(4,0)
print(fp.tell())
fp.truncate()
print(fp.tell())

文件内容:

1234

输出结果:

4
4

首先将文件指针转到倒数第二个位置,truncate()不加参数就将该位置后的内容截断。

flush()

用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要被动的等待输出缓冲区写入。一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。

close() :

刷新缓冲区里任何还没有写入的信息,并关闭文件,之后便不可再对该文件进行读写。

二.python中的文件指针:

当我们读取文件内容时,并不能重复的读取,比如一个txt文件里有"12345"内容,用两个read()方法读取该txt的内容,会发现,第一个返回文件内容,第二个返回空字符串。这其实都是因为文件指针的问题。下面结合文件基本方法read(),write()来理解一下文件指针。

read():

该方法读取文件中从文件指针当前位置开始,长度为size的文件内容。读取完成后文件指针移动到读取到的最后一个字节处。

fp = open(r"test.txt", "r+")#打开后文件指针在文件起始位置
print(fp.tell())
fp.read(2)
print(fp.tell())

0
2

从上可以看出开始时文件指针在文件开头,当使用fp.read(2)之后,文件指针指向第2个位置。

write(str):

该方法从文件指针当前位置开始,向文件中写入str中的内容。如对应位置有内容则直接覆盖,写入完成之后文件指针指向写入字符串在文件中的对应位置。
源文件内容:

12345

fp = open(r"test.txt", "r+")#打开后文件指针在文件末尾位置
print(fp.tell())
fp.write("www")
print(fp.tell())

文件内容:

www45

输出结果

0
3

当fp.write(“www”)之后文件指针指向3。

seek(偏移量,[起始位置]):

用来移动文件指针。
偏移量: 单位为字节,可正可负
起始位置: 0 - 文件头, 默认值; 1 - 当前位置; 2 - 文件尾

fp = open(r"test.txt", "a+")#打开后文件指针在文件末尾位置
print(fp.tell())
fp.seek(0)
print(fp.tell())

结果:

5
0

fp = open(r"test.txt", "r+")#打开后文件指针在文件起始位置
print(fp.tell())
fp.seek(0,2)
print(fp.tell())

结果:

0
5

注意

‘w+’模式例子:如果在打开文件和关闭文件之间先执行读操作然后执行写操作,最后读出的内容为空。

原文件内容:

12345

fp = open(r"test.txt", "w+")#打开后文件指针在文件起始位置
print(fp.tell())
fp.write("www")
print(fp.tell())
print(fp.read())

文件内容:

www

输出结果:

0
3

并未输出文件中的内容,这是因为首先打开文件时会将文件中的内容清空,然后在我们执行fp.write()方法之后文件指针位于文件的末尾,而read()方法是读取当前指针位置向后size长度的内容。因此输出为空。

‘r+’模式例子1:如果在打开文件和关闭文件之间先执行写操作然后读操作,读出的内容是写入后未覆盖的内容,若都覆盖则读出为空。

原文件内容

12345

fp = open(r"test.txt", "r+")#打开后文件指针在文件起始位置
print(fp.tell())
fp.write("www")
print(fp.tell())
print(fp.read())

文件内容:

www45

输出

0
3
45

首先以r+模式打开,文件指针在文件起始位置,然后写入"www"之后,指针移动到3所以只能读到最后两个位置上的元素45

"a+"模式打开的文件,无论如何改变文件指针位置,最终执行write()方法时依旧是在文件末尾写入。

原文件内容:

12345

fp = open("test.txt",'a+')
data = "www"
fp.seek(0)
print(fp.tell())
fp.write(data)
print(fp.tell())

文件内容

12345www

输出结果:

0
8

可以看出在执行write()方法之前已经将指针移到起始位置,但是依旧写到了文件的末尾。

三.关于文件起始位置插入内容的问题:

今天遇到了一个问题,需要将一串按照时间倒序存储的列表顺序插入到文档中。具体问题是这样的,有两个列表,一个记录时间,一个记录内容,它们的关系就是:每个内容的发表时间。但是是按照时间倒序排列的。例如:

time_list = ['2月15日','','','2月14日','2月11日','','']
content_list=['晚上我锻炼了身体','下午我看了一篇论文','今天过了情人节','早上做了做饭','今天下午打了篮球','上午在家学习','早上8点起床']

我希望得到的结果是按照时间顺序排列:
在这里插入图片描述
并且同样一天的消息要放在对应的时间下面。这个看似简单的问题废了我很长的时间。
下面就一步一步分享一下我的思考过程以及解决思路:

首先要考虑如何在文件的起始位置插入内容


  1. 代码1

    fp = open("test.txt",'r+')
    data = "www"
    fp.write(data)
    

    考虑通过r+方式打开文件指针在起始位置,但是通过“二”中的分析,我们知道这个方法行不通,因为会覆盖之前的内容。

  2. 代码2:
    原文件内容:

    12345

    fp = open("test.txt",'r+')
    data = "www"
    old = fp.read()
    fp.write(data)
    fp.write(old)
    

    文件内容:

    12345www12345

    考虑先保存原有内容,然后写入新的内容,再把之前的内容写入,发现不对。原因是在read()之后,文件指针位置移动到文件末尾,所以出现问题。
    改进

    	fp = open("test.txt",'r+')
    	data = "www"
    	old = fp.read()
    	fp.seek(0)
    	fp.write(data)
    	fp.write(old)
    

    经过修改之后则可以顺利的完成在起始位置插入的操作。

  3. 代码3:

    fp = open("test.txt",'a+')
    data = "www"
    fp.seek(0)
    old = fp.read()
    fp.seek(0)
    fp.write(data)
    fp.write(old)
    

    考虑到a+模式指针位置在最后,所以先移动到最前面再进行插入,但是由于模式为a+所以在写的时候无论指针在哪都会写在文件末尾。该方法不行,在"二"中的注意部分有具体演示
    改进

    fp = open("test.txt",'a+')
    data = "www"
    fp.seek(0)
    old = fp.read()
    fp.truncate(0)
    fp.write(data)
    fp.write(old)
    

    这里在读完原内容之后,执行truncate(0)将文件从起始位置截断,也就是说当前文件变为了空文件,所以后面的两步写操作就和正常的写入一样了。


    在了解了文件基本操作以及文件指针和在文件起始位置插入内容的方法之后,开始考虑我们的问题

    这里我提供一种我的思路:如下所示,要考虑清楚每一步文件指针的变化,这样才能让我们更加灵活的实现我们想要的操作。

    time_list = ['2月15日','','','2月14日','2月11日','','']
    content_list=['晚上我锻炼了身体','下午我看了一篇论文','早上做了做饭','今天过了情人节','今天下午打了篮球','上午在家学习','早上8点起床']
    fp_pointer = 0
    fp = open("test.txt",'r+',encoding="utf8")
    for i in range(len(content_list)):
        if time_list[0] == "":
            fp.seek(fp_pointer, 0)#指针指向上一条动态内容的最后一个位置
            old = fp.read()#指针指向上一条动态之后的所有内容
            fp.seek(fp_pointer, 0)#指针指向上一条动态内容的最后一个位置
            fp.write(content_list[0])#写入该条动态内容
            fp.write("\n")
            fp.write("\n")
            fp_pointer = fp.tell()#保存该条动态内容的最后一个位置。
            fp.write(old)#将上一条动态之后的所有内容重新写入
    
        else:
            fp.seek(0)#将文件指针指向起始位置
            old = fp.read()#保存原有内容
            fp.seek(0)#因为读取内容之后,文件指针会移动到末尾,将文件指针指向起始位置
            fp.write(time_list[0])
            fp.write("\n")
            fp.write(content_list[0])
            fp.write("\n")
            fp.write("\n")
            fp_pointer = fp.tell()#保存该条动态内容的最后一个位置
            fp.write(old)#重新写入原有内容
        time_list.pop(0)
        content_list.pop(0)
    

    因为文件一直处于打开的状态,所以在经过read()和write()时都会发生文件指针变化的问题,比如我们现在要插入第二条动态,其对应的时间为"",所以需要插入到第一条动态之后,那么我们就需要将文件指针移动到第一条动态对应的最后一个位置,所以我们用fp_pointer来记录上一条动态的最后一个元素位置。然后我们通过read()将该位置之后的所有内容存入old中,此时文件指针指向了文件末尾,我们需要再次移动指针位置到上一条动态的最后一个位置,然后写入第二条动态,最后将old写入即可。

    若我们要插入第4条动态,其对应的时间为"2月14日",此时我们只需要将文件中原有内容都存入old,然后将指针指向文件起始位置,最后将动态及old中的内容写入即可。

四.参考文献

https://www.cnblogs.com/hyyq/p/8972595.html
https://blog.csdn.net/weixin_31083103/article/details/113659606
https://blog.csdn.net/weixin_39800957/article/details/110779673
https://www.runoob.com/python/python-func-open.html

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐