文件操作的那些坑事
直接使用底层的文件操作函数,还是会遇到一些坑事的。特别是接触底层较少或者新来的童鞋。。。
一个简单的需求
将一个文件的前几行保留,后面的数据写入到另一个文件。
当然,此处不讨论awk、sed、shell中的方便的命令。单纯从文件操作来讨论下做法。
思路,很简单:打开原始文件,读取所有内容,擦除原始文件,将前n行写入原始文件,将后续内容写入第二个文件。
那么问题来了。
1、以什么方式打开原始文件
只能是”r+”方式或者”a+”方式。而且”a+”方式在读文件时需要先seek(0)。
如果你用”w+”方式,恭喜你,你读出的内容永远为空。为啥子呢,因为”w+”方式默认打开文件时就将文件截断为空了。里面的内容你当然取不到。。。。
如果你用”a+”方式,以文件操作函数这尿性,大概率可以写入文件,但是文件前一段永远都是空白。为啥,因为你可以seek(0)然后写入,但是你写入的内容还是会附加在文件末尾。这库函数就是这么执著。。。。真那啥。。。。。。。当然,这点我还没有测试,有兴趣的可以试下。。。。前面2个都是亲自试过了。。。。
ps:后来试了下”a+”,直接读还是读不出内容来。。。。坑爹。。。seek(0)之后,可以读出文件来。然后写入文件,倒是没有出现洞。。。。
是不是有些那啥。。。。
2、如何清空原始文件内容
在python里,有个truncate方法。将文件截断,但是这个方法对于不大熟悉的人来说还是有些事的。。。
truncate(size),从文件开头处将文件截断为size字节。如果不指定size,将当前位置后的所有内容清除截断。。。。有点那啥吧。。。
3、你以为你截断完文件然后写入前几行就完了么
不是那样的。当你将文件截断为0字节后,如果你直接将前内行的内容写入文件,打开文件后你会看到你写入的内容不是从第一行开始,而是前面有一大段的空白。。。。。。
坑爹吧。。。。。
为啥这样呢。因为文件有洞的概念。当你截断文件后,文件内容是被清除了,但是位置还是在之前你某次操作后的位置上。例如你读取所有文件内容,那么位置将在文件末尾。
然后当你写入文件时,是从文件的末尾开始写入的。虽然之前的内容都被删除了。。。。
坑爹啊。。。
所以,你需要做的是还要加上seek(0)。让位置指向文件开头。。。。
附上一段python代码
def split_file_by_line(raw_file, new_file,line_pos):
with open(raw_file, "r+") as f:
with open(new_file, "w+") as f2:
lines = f.readlines()
f.seek(0)
f.truncate(0)
f.writelines(lines[0:line_pos-1])
f2.writelines(lines[line_pos - 1:])
写起底层代码来,小节目真是多啊。。。。:)