背景

python读写文件,是最基本的文件操作,熟悉每种读写方法,大大加快工作效率。使用场景不用多说,可以作为数据参数化的开端,也可以作为数据生成的末端。

read() readline() readlines() 的区别和用法

<1>read() 读取整个文件,将文件内容放到一个字符串变量中, 不适用于读取大文件

f = open('C:\\Users\\pengfei\\Desktop\\000', 'r+', encoding='utf-8', errors='ignore')
lines = f.read()
print(lines)
print(type(lines))
f.close()

<2>readline()方法每次读取一行;返回的是一个字符串对象,保持当前行的内存,不占用内存

f = open('C:\\Users\\pengfei\\Desktop\\000', 'r+', encoding='utf-8', errors='ignore')
print("读取一行 ====")
line = f.readline()
while line:
# 打印当前文件指针的位置
    print("文件指针:", f.tell())
    print("行内容:", line)
    line = f.readline()

<3>readlines() 一次性读取整个文件;自动将文件内容分析成一个行的列表

f = open('C:\\Users\\pengfei\\Desktop\\000', 'r+', encoding='utf-8', errors='ignore')
print("读取多行 ====")
print(f.readlines())

注意 :选择使用readlines()方法,一次性读取文本所有内容,返回结果为list,其中每个元素结尾有"\n"。该方法适合读取配置文件,速度较快,但是文本越大占用内存越大。这种方法读取的文本内容,每行文本末尾都会带一个’\n’换行符 (可以使用L.rstrip(’\n’)去掉换行符)

write() writelines()方法

写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件:

>>> f = open('test.txt', 'w') # 若是'wb'就表示写二进制文件
>>> f.write('Hello, world!')
>>> f.close()

如果没有这个文件,就创建一个;如果有,那么就会先把原文件的内容清空再写入新的东西。所以若不想清空原来的内容而是直接在后面追加新的内容,就用’a’这个模式。

我们可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:

with open('test.txt', 'w') as f:
    f.write('Hello, world!')

python文件对象提供了两个“写”方法: write() 和 writelines()。
write()方法和read()、readline()方法对应,是将字符串写入到文件中。
writelines()方法和readlines()方法对应,也是针对列表的操作。它接收一个字符串列表作为参数,将他们写入到文件中,换行符不会自动的加入,因此,需要显式的加入换行符。

f1 = open('test1.txt', 'w')
f1.writelines(["1", "2", "3"])
# 此时test1.txt的内容为:123
f1 = open('test1.txt', 'w')
f1.writelines(["1\n", "2\n", "3\n"])
# 此时test1.txt的内容为:
# 1
# 2
# 3

关于open()的mode参数:

‘r’:读
 ‘w’:写
 ‘a’:追加
 ‘r+’ == r+w(可读可写,文件若不存在就报错(IOError))
 ‘w+’ == w+r(可读可写,文件若不存在就创建)
 ‘a+’ ==a+r(可追加可写,文件若不存在就创建)
 对应的,如果是二进制文件,就都加一个b就好啦:
 ‘rb’  ‘wb’  ‘ab’  ‘rb+’  ‘wb+’  ‘ab+’

字符串编码问题:
遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

>>> f = open('test.txt', 'r', encoding='gbk', errors='ignore')

出个练习读写的案例:
有两个文件,每个都有很多行ip地址,求出两个文件中相同的ip地址

import bisect

with open('test.txt', 'r') as f1:
    list1 = f1.readlines()
for i in range(0, len(list1)):
    list1[i] = list1[i].strip('\n')
with open('test1.txt', 'r') as f2:
    list2 = f2.readlines()
for i in range(0, len(list2)):
    list2[i] = list2[i].strip('\n')

list2.sort()
length_2 = len(list2)
same_data = []
for i in list1:
    pos = bisect.bisect_left(list2, i)
    if pos < len(list2) and list2[pos] == i:
        same_data.append(i)
        same_data = list(set(same_data))
print(same_data)