文件操作

一. 数据类型之间的补充

str <--> list split join
list <--> set set(list) list(set())
list <--> tuple tuple(list) list(tuple)

bool False: "" [] () set() {}
这里注意 空集合一定要用 set() 表示

tuple:
元组里只有一个元素时,后面一定要加逗号。
否则就不是元组,而是该元素对应的数据类型

list:
在循环一个列表时,最好不要改变列表的长度,否则会影响结果。
但是可以采用倒叙法:
for i in range(len(l1)-1, -1, -1):
pass

dict:
在循环一个字典时,不能改变字典的长度,否则会报错

二. 小数据池、代码块与编码总结
is id ==
== 比较的是两边的数值是否相同
id() 对象的内存地址
内存地址相同,意味着相互比较的变量在内存中指向的是同一个内存地址
is 比较的是两个变量指向的是内存中同一个地址

代码块:
简单来说,是一个文件。命令行的一行就是一个代码块
同一代码块中的缓存机制
适用的数据类型:str int bool
意义:
1. 节省内存
2. 提高性能

编码进阶:
ascii unicode utf-8 gbk
1. 不同编码之间不能相互识别. (乱码或出错)
2. 网络传输和数据存储不能是通过Unicode的编码方式

Python3x
str --> 内部编码方式 Unicode
它不能进行直接的网络传输和数据的存储

unicode --> a = s.encode("gbk")
gbk --> a.decode("gbk")
unicode --> b = s.encode("utf-8")
utf-8 --> b.decode("utf-8")

a gbk的bytes类型
gbk --> utf-8
a.decode('gbk').encode("utf-8")

三. 深浅copy
l1 = [1, 2, 3]
l2 = l1.copy()
copy:
在内存中创建新的列表,但列表内的元素与原列表的都指向同一个内存地址

import copy
l1 = [1, 2, 3, [33, 220]]
l2 = copy.deepcopy(l1)
copy:
在内存中创建一个新的列表
列表中不可变的数据类型与原列表的同一个元素指向的是同一个内存地址,
可变的数据类型与原列表的同一个元素指向内存中不同的地址

四. 文件操作

注意,一般不用 + 的模式,比如 a+ b+ 什么的

1. 如果想要通过Python代码操作某个文件,必须要有以下三要素:
1. path:文件的路径
2. mode: r w r+ w+ a ...
3. encoding: 编码方式
2. f1 f file file_handler, f_h... 文件句柄
open() 内置函数,这个函数实际上是调用的操作系统对文件操作的功能
windows:默认的编码方式是 gbk
linux: 默认的编码方式是 utf-8
IOS: 默认的编码方式是 utf-8
接下来对文件的任何操作都需要借助文件句柄
f.close() 如果不关闭文件,该文件就一直在内存中占用资源

3. 文件操作步骤:
1). 打开文件产生文件句柄
path, encoding, mode
2).

写(w wb w+ w+b)
追加(a ab a+ a+b)
文件操作的其他功能
文件的改的操作

 1 # 创建代码:
 2 
 3 f1 = open(r"G:	est.txt", encoding="utf-8", mode="r")
 4 content = f1.read()
 5 print(content)
 6 
 7 f1.close()
 8 
 9 
10 # 报错原因:
11 
12 # 1. 路径错误.
13 #     比如这里的 "G:	est.txt",系统会认为 	 是一个转义字符
14 #     解决办法:
15 #         1). "G:\test.txt"
16 #         2). r"G:	est.txt"
17 #    这里不能直接把反斜杠改为斜杠,因为不同系统之间的斜杠与反斜杠之间会有不同的定义
18 
19 # 2. UnicodeDecodeError: 编码问题
20 #     有时候会用记事本创建一个 .txt 文件,有时候会在Pycharm里创建一个 .txt文件等。
21 #     这样会导致一个结果,即程序里默认的编码方式与创建的新文件的编码方式不一样,导致运行程序时报错或者乱码

 
路径:
绝对路径:从磁盘(根目录)开始,直到找到文件。
相对路径:当前路径(当前文件夹)找到的文件。
比如上面的 test.txt 文件如果就在当前文件夹,可以这样写:
f1 = open("test", encoding="utf-8", mode="r")
 1 # r 模式下的五种读取方式
 2 
 3 # 1. read() 全部读取出来
 4 
 5 # 2. read(n) 读n个字符
 6 # 注意这里使用的是绝对路径,所以可以这样写
 7 # 即与该Python文件是在同一个文件夹
 8 f1 = open("test.txt", encoding="utf-8", mode="r")
 9 content = f1.read(3)
10 print(content)
11 
12 f1.close()
13 
14 # 运行结果:  这是一
15 # 由此得知 r 模式是按照字符读取一个元素的
16 
17 # 3. readline() 按行读取
18 
19 f1 = open("test.txt", encoding="utf-8", mode="r")
20 content = f1.readline()
21 print(content, type(content))
22 print(content, type(content))
23 
24 f1.close()
25 
26 # 以下是运行结果
27 # 这是一个测试
28 #  <class 'str'>
29 # 这是一个测试
30 # <class 'str'>
31 
32 # 4. readlines() 返回一个列表
33 
34 f1 = open("test.txt", encoding="utf-8", mode="r")
35 content = f1.readlines()
36 print(content, type(content))
37 
38 f1.close()
39 
40 # ['这是一个测试
', 'this is a test...
'] <class 'list'>
41 
42 # 5. 使用前面四种方法的大前提:
43 #    文件必须比较小
44 #    比如一个文件有9G,而电脑内存只有8G,如果使用下面四种方法,内存就会挂掉。解决办法:使用 for 循环
45 
46 f1 = open("test.txt", encoding="utf-8")
47 for line in f1:
48     print(line.strip())
49 f1.close()
 1 # rb 模式 (也有五种读取方法)
 2 
 3 f1 = open("test.txt", mode="rb")
 4 print(f1.read(3))
 5 
 6 f1.close()
 7 
 8 # b'xe8xbfx99xe6x98xafxe4xb8
 9 # x80xe4xb8xaaxe6xb5x8bxe8xaf
10 # x95
this is a test...
'
11 
12 # 因此得知 rb 模式是按照字节读取一个元素的
13 # 注意与 r 模式的对比
14 
15 # 这里 f1 对应的那行之所以不加 encoding="utf-8"
16 # 是因为这个模式读取的就是元素的字节,没有解码
17 # 可以解码看一下
18 # print(f1.read(6).decode("utf-8"))   
19 # 运行结果:  这
 1 # w 模式
 2 # 没有文件创建文件写入,有文件清空文件内容重新写入新内容
 3 f = open(r"G:	est1.txt", encoding="utf-8", mode="w")
 4 f.write("这是一个测试")
 5 f.close()
 6 # 因为没有这个文件,所以它会创建这个文件
 7 # 如果有文件,且有内容,比如现在将
 8 # f.write("这是一个测试") 的字符串内容改为 "中国"
 9 # 发现该文件的内容变为 "中国"了
10 
11 # 在同一个文件句柄里写入多个内容是不会再清空内容的
12 # 但是文件要是关闭了再以写模式打开的话就会再次清空
13 # 必须先在前一个程序里关闭该文件,才能在后面再写程序再次打开该文件
14 
15 f = open(r"G:	est1.txt", encoding="utf-8", mode="w")
16 f.write("这里替换掉原来的内容了")
17 f.write("这里替换掉原来的内容了")
18 f.write("这里替换掉原来的内容了")
19 
20 f.close()
21 
22 # 在同一个文件句柄里写入多个内容是不会再清空内容的
23 # 所以该文件有三句 "这里替换掉原来的内容了"
24 
25 
26 f2 = open(r"G:	est1.txt", encoding="utf-8", mode="w")
27 f2.write("这里变成666了")
28 f2.write("这里变成666了")
29 f2.write("这里变成666了")
30 
31 f2.close()
32 
33 # 打开 test1.txt 文件,发现内容变成三句
34 # "这里变成666了"
1 # wb 模式
2  
3 f1 = open('cat.jpg',mode='rb')
4 content = f1.read()  
5 # 以bytes读取原图片获取数据
6 f1.close()
7 f2 = open('cat.jpg',mode='wb')
8 f2.write(content)        # 将数据写入到一个新文件图片
9 f2.close()                # 完成了对原图片的复制。
 1 # 追加模式 a ab a+ a+b
 2 # 没有文件创建文件追加内容
 3 # 有文件在原文件的末尾添加新内容
 4 
 5 f1 = open('file3.txt', encoding='utf-8', mode='a')
 6 f1.write('老男孩教育!')
 7 f1.close()
 8 
 9 f1 = open('file3.txt', encoding='utf-8', mode='a')
10 f1.write('太白金星')
11 f1.close()
1 # r+ 读写模式,先读后写(追加)
2 
3 f1 = open(r"G:	est.txt", encoding="utf-8", mode="r+")
4 content = f1.read()
5 print(content)
6 f1.write("添加内容")
7 f1.close()
 1 # 如果在 r+ 模式下是先写后读
 2 
 3 f1 = open(r"G:	est.txt", encoding="utf-8", mode="r+")
 4 f1.write("添加内容")
 5 content = f1.read()
 6 print(content)
 7 f1.close()
 8 
 9 # 运行发现,因为是先写,"添加内容"就在文件开头了
10 # 这里涉及到光标问题,一打开文件,光标是按照先读或者先写来确定的
11 # 如果是先读后写
12 # 那么一打开文件光标就落在文件之前所写内容的后面,这样再写的话就顺理成章了
13 # 但是先写再读的话
14 # 一打开文件光标就落在文件开头,会直接覆盖掉前面对应字节的内容
15 
16 # 因此运行结果:
17 # 为什么是 "个测试", 而不是 "添加内容个测试"
18 # 因为先写再读时,写的这句代码运行后,光标就落在个的前面了,所以从 "个" 开始打印结果
19 
20 # 个测试
21 # this is a test...
22 # 添加内容
23 
24 # 而且该 .txt 文件的内容已经变为:
25 
26 # 添加内容个测试
27 # this is a test...
28 # 添加内容
1 # w+ :写读模式
2 # 先写后读,会先清空原内容,很少用这个模式
3 
4 f1 = open('file2.txt', encoding='utf-8', mode='w+')
5 f1.write('66666666')
6 f1.seek(0)
7 print(f1.read())
8 f1.close()
1 # flush 相当于强制保存 (ctrl+c)
2 
3 f1 = open(r"G:	est3.txt", encoding="utf-8", mode="w")
4 f1.write("添加内容")
5 f1.flush()
6 f1.close()
 1 # readable 判断一个文件句柄是否可读,可写
 2 
 3 f1 = open(r"G:	est3.txt", encoding="utf-8", mode="w")
 4 f1.write("添加内容")
 5 print(f1.readable())
 6 if f1.readable():
 7     f1.read()
 8 f1.close()
 9 
10 # 测试是否可读,因为前面的 mode="w",因此不能读
11
12 # 以 r+ 模式打开一个文件,比如 a.txt,判断它是否可读可写的方法
13 with open("a.txt", encoding="uft-8", mode="r"):
14 print("可读?>>>":{}".format(f.readable()), "可写?>>>:{}".format(f.writable()))
15
16 # 或者这样
17 f = open("t1", encoding="utf-8", mode="r+")
18 if f.readable() and f.writable():
19 print("可读、可写")
20 f.close()

 1 # seek tell 按照字节调整、读取光标位置
 2 
 3 f1 = open(r"G:	est3.txt", encoding="utf-8")
 4 ret = f1.read()
 5 print(f1.tell())
 6 # 告诉我们光标在哪个位置
 7 # 这里因为有 read(),即执行这步时就已经读完所有内容了
 8 # 所以光标此时在最后一个字符的末尾位置
 9 
10 f1.seek(3)
11 # 这里如果 3 改为比 3 更小的数,会报错
12 # 因为第一个是汉字,在 "utf-8" 编码方式下,它至少需要3个字符
13 print(f1.read())
14 f1.close()
15 
16 # 上面是指定光标位置,3 表示光标跳第一个汉字的后面
17 # 所以打印结果会少了第一个汉字
 1 # truncate()
 2 # 只能从头截取,不能调整光标方式来截取一部分内容
 3 # 不能在 w 模式下使用,因为会先清空内容
 4 # 如果非得使用 truncate() 的话,会取空的东西
 5 
 6 f1 = open('file4.txt', encoding='utf-8',mode='r+')    # truncate() 只能在 r+ a+ 模式下使用?
 7 f1.seek(9)
 8 ret = f1.truncate(6)
 9 # print(ret)
10 f1.close()
 1 # 文件的改操作
 2 
 3 # 不管怎么操作文件,最后总得关闭文件
 4 # 为了防止忘记写 f.close() 导致浪费内存
 5 # 可以使用 with open 来管理上下文
 6 
 7 with open(r"G:	est3.txt", encoding="utf-8") as f1:
 8     content = f1.read()
 9     print(content)
10 
11 # 好处:
12 # 1. 可以自动关闭文件,无需再写 f.close()
13 # 2. 可以同时打开多个文件, 比如:
14 
15 with open(r"G:	est3.txt", encoding="utf-8") as f1, open(r"G:	est2.txt", encoding="utf-8", mode="w") as f1:
16 
17 # 这里还有个问题,Python规定一行的代码不能超过79个字符
18 # 所以可以加个 斜杠把另一个 open 语句放到下一行:
19 
20 with open(r"G:	est3.txt", encoding="utf-8") as f1, 
21     open(r"G:	est2.txt", encoding="utf-8", mode="w") as f1:
22 
23 # 使用 f = open 还是 with open 要看情况
24 # 如果每次只处理每个文件的一个模式,可以使用 with open
25 # 如果对某一个文件又有读操作又有写操作,最好用 f = open 模式,因为 with open 自动关闭文件需要一段时间
26 # 比如这里如果该文件还没关闭的情况下又对该文件操作的话会报错, EOL Error
27 
28 with open(r"G:	est3.txt", encoding="utf-8") as f1:
29     f1.read()
30     with open(r"G:	est3.txt", encoding="utf-8") as f2:
31         f2.write("666")
 1 # 文件的改:
 2 # 1. 以读的模式打开原文件,产生文件句柄f1
 3 # 2. 以写的模式打开新文件,产生文件句柄f2
 4 # 3. 读取原文件,将原文件的内容改写成新内容写入新文件
 5 # 4. 删除原文件
 6 # 5. 将新文件重命名为原文件名
 7 # 将文件中所有的alex都替换成大写的SB(文件的改的操作)
 8 import os
 9 
10 # 第一步和第二步
11 with open(r"G:例子.txt", encoding="utf-8") as f1, 
12     open(r"G:例子2.txt", encoding="utf-8", mode="w") as f2:
13 # 第三步
14     old_content = f1.read()
15     new_content = old_content.replace("alex", "SB")
16     f2.write(new_content)
17 # 第四步
18 os.remove("例子.txt")
19 # 第五步
20 os.rename("例子2.txt", "例子")
21 
22 # 这个方法有不足的情况,就是文件太大的情况占用内存,所以应该用 for 循环
23 # for 循环每次读取文件的第一个元素,再循环的时候新的第一个元素会把之前的元素覆盖掉,也就是说,在内存中只占一个位置
24 
25 import os
26 
27 with open("例子", encoding="utf-8") as f1, 
28     open("例子2", encoding="utf-8", mode="w") as f2:
29     for line in f1:
30         line = line.replace("alex", "SB")
31         f2.write(line)
32 os.remove("例子")
33 os.rename("例子2", "例子")


原文地址:https://www.cnblogs.com/shawnhuang/p/10185016.html