1 # 应用程序运行过程中产生的数据都是存放在内存中的,若想永久保存下来,必须存放在硬盘中
2 # 应用程序操作硬件必须通过操作系统,而文件就是操作系统提供给应用程序来操作硬盘的虚拟概念
3 # 用户或者应用程序对文件的操作,就是向操作系统发起调用,然后由操作系统完成对硬盘的具体操作
4 # 有了文件的概念,我们无需考虑操作硬盘的细节,只需要关注文件操作即可
5
6 # 打开文件,由应用程序向操作系统发起系统调用open(),操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给一个变量f
7 f = open('a.txt', 'r', encoding='utf-8')
8 # 调用文件下的读/写方法,会自动转成硬盘的读/写操作
9 data = f.read()
10 # 打印读出来的数据
11 print(data)
12
13 # 向操作系统发起关闭文件的请求,回收系统资源
14 f.close() # 回收变量操作系统打开的文件资源
15 del f # 回收应用程序级
16 print(f)
17
18 # 资源回收和with上下文管理
19 # 打开一个文件包含两部分资源:应用程序的变量f和操作系统打开的文件。
20 # 在操作完毕一个文件时,必须把这两部分资源全部回收
21 # del f 一定要发生在f.close()之后,否则就会导致操作系统打开的文件无法关闭,白白
22 # 占用资源
23
24 # python自动垃圾回收机制决定了我们无需考虑del f,这就要求我们在操作文笔文件后
25 # 一定要f.close(),虽然我们如此强调,但是大多数的人还是会忘记f.close()
26 # 考虑到这一点,python提供了with关键字来帮我们管理上下文
27 # 可用with打开多个文件,中间用,分隔就行
28 with open('a.txt', 'r', encoding='utf-8') as read_f, open('b.txt', 'w', encoding='utf-8') as write_f:
29 res = read_f.read()
30 write_f.write(res)
31
32 # 指定操作文本文件的字符编码
33 #
34 # 由操作系统打开文件,如果打开的是文本文件,则会涉及到字符编码问题,如果没有为open()指定编码,那么打开文本文件的默认编码很明显就是操作系统说了算
35 # 操作系统会用自己的默认编码去打开文件,在windows下默认是gbk,linux下默认是utf-8。
36 #
37 # 要想保证不乱码,怎么存的就怎么取。
38 # pycharm默认存文件时以utf-8存的,所以取的时候也应该是utf-8,不然会乱码
39 with open('a.txt', 'r', encoding='gbk') as f:
40 print(f.read()) # 乱码
41
42 with open('a.txt', 'r', encoding='utf-8') as f:
43 print(f.read()) # 正常展示
44
45 # 文件的操作模式
46 # 控制文件读写操作的模式
47 # r(默认):只读
48 # w:只写
49 # a:只追加写
50
51 # r模式的案例使用
52 # r模式当文件不存在时报错,当文件存在时文件内指针跳到文件开头
53 with open('a.txt', 'r', encoding='utf-8') as f:
54 res = f.read()
55 print(res)
56 # 哈哈哈哈哈哈
57 # 呵呵呵呵呵呵
58 #
59 # 实现用户登录功能
60 inp_username = input('请输入你的姓名:').strip()
61 inp_password = input('请输入你的密码').strip()
62
63 with open(r'property.txt', mode='r', encoding='utf-8') as f:
64 for line in f:
65 u, p = line.strip('\n').split(':')
66 if u == inp_username and p == inp_password:
67 print('{name}登录成功'.format(name=u))
68 break
69 else:
70 print('用户名或者密码错误,请重新输入')
71 # w模式的使用
72 # w只写模式:在文件不存在时创建空文档,文件存在时则清空文件,文件指针跑到文件开头
73
74 with open('c.txt', 'w', encoding='utf-8') as f:
75 f.write('你好')
76 f.write('我好')
77 f.write('大家好好')
78 f.write('才是\n真的好')
79
80 with open('c.txt', 'w', encoding='utf-8') as f:
81 f.write('哈哈哈')
82 f.write('呵呵呵')
83
84 # 在文件不关闭的情况下,连续的写入,后写的内容一定跟在前写内容的后面。
85 # 如果重新以w模式打开写入,则会清空文件内容
86 #
87 # a(只追加写模式)模式的使用:在文件不存在时创建文件,在文件存在时会将文件指针移动到文件末尾
88
89 with open('d.txt','a',encoding='utf-8') as f:
90 f.write('第一行')
91 f.write('\n第二行')
92
93 # a模式与w模式的异同:
94 # 相同点:在打开的文件不关闭的情况下,连续的写入,新写的内容总会跟在前写的内容之后
95 # 不同点:以a模式重新打开文件,不会清空原文件,会将文件指针移动到文件末尾。新写的内容永远写在最后。
96
97 # a模式实现注册功能
98 while True:
99 username = input('请输入你的用户名:')
100 password = input('请输入你的密码')
101
102 if username == 'quit':
103 break
104
105 with open('db.txt', 'a', encoding='utf-8') as f:
106 info = '%s:%s\n' % (username, password)
107 f.write(info)
108
109
110 # +模式的使用
111
112 # r+,w+,a+ 可读可写
113
114
115 # 控制文件读写内容的模式
116 # 大前提:tb模式均不能单独使用,必须与rwa之一结合使用
117 # t(默认的):文本模式
118 # 1、读写文件都是以字符串为单位的
119 # 2、只能针对文本文件
120 # 3、必须指定encoding参数
121
122 # b:二进制模式
123 # 1、读写文件都是以bytes/二进制为单位的
124 # 2、可以针对所有文件
125 # 3、一定不能指定encoding参数
126
127 # t模式的使用
128
129 with open('test1.txt', 'rt', encoding='utf-8') as f:
130 res = f.read()
131 print(res)
132
133 with open('test2.txt', 'wt', encoding='utf-8') as f:
134 f.write('我写了')
135 f.write('我写了')
136 f.write('我写了\n') # 写入的必须是字符串类型
137
138 with open('test3.txt', 'at', encoding='utf-8') as f:
139 f.write('测试哈哈哈哈') # 写入的必须是字符串类型
140 f.write('测试哈哈哈哈')
141 f.write('测试哈哈哈哈')
142 f.write('测试哈哈哈哈')
143
144 # t模式只能用于操作文本文件,无论读写都应该以字符串为单位,而存取硬盘本质都是二进制形式,当指定t模式时,内部
145 # 已经帮我们做了编码与解码
146
147 # b模式的使用
148 with open('09 磁盘.mp4','rb') as f:
149 res = f.read()
150 print(res)
151 print(type(res))
152
153 with open('wb.txt', 'wb') as f:
154 msg = '哈喽呀哈哈哈哈傻逼'
155 msg_b = msg.encode('utf-8')
156 f.write(msg_b) # b模式写入的数据必须是bytes类型
157
158 # 强调:b模式对比t模式
159 # 在操作纯文本文件方面,t模式帮我们省去了编码与解码的环节,b模式则需要手动编码与解码,所以t模式更加方便
160 # 针对非文本文件,如(图片、视频、音频),则b模式更加方便
161
162 # 编写拷贝工具
163
164 src_file = input('请输入源文件路径:').strip()
165 dest_file = input('请输入目标文件路径').strip()
166
167 with open(r'%s' % src_file, 'rb') as read_f, open(r'%s' % dest_file, 'wb') as write_f:
168 write_f.write(read_f.read())
1 # 操作文件的方法:
2 # f.read() 读取所有内容,执行完该操作后文件指针会移动到文件末尾
3 # f.readline() 读取一行内容,光标移动到第二行的头部
4 # f.readlines() 读取每一行内容,存放于列表中,光标移动到文件末尾
5
6 # f.read()和f.readlines都是将内容一次性读入,如果内容过大会导致内存溢出,若还想将内容全部读入内存,则必须分多次读入
7 import time
8
9 with open('xxx1.txt', 'rt', encoding='utf-8') as f:
10 for line in f:
11 print(line, end='') # 以文本内容为例通过for循环每次只读取一行数据
12
13 # with open('09 磁盘.mp4', 'rb') as f:
14 # while True:
15 # data = f.read(1024)
16 # if len(data) == 0:
17 # break
18 # print(data)
19
20 with open('xxx2.txt', 'at', encoding='utf-8') as f:
21 f.write('111\n222\n333\n')
22 f.writelines(['aaa\n', 'bbb\n']) # 写入多行
23
24 with open('xxx3.txt', 'ab') as f:
25 f.write('111\n222\n333\n'.encode('utf-8'))
26 f.writelines([bytes('aaa\n'.encode('utf-8')), bytes('bbb\n'.encode('utf-8'))])
27
28 # 文件是否可读:f.readable
29 # 文件是否可写:f.writeable
30 # 文件是否关闭:f.closed
31 # 文件的编码:f.encoding 如果文件是以b模式打开的,则没有该属性
32 # 立刻将文件的内容刷新到硬盘 f.flush
33 # f.name
34
35 # 主动控制文件内指针的移动
36 # 强调:文件内指针的移动都是以Bytes为单位的,唯一例外的就是t模式下的read(n)方法,是以字符为单位的。
37
38 with open('xxx4.txt', 'rt', encoding='utf-8') as f:
39 res = f.read(3)
40 print(res)
41
42 with open('xxx4.txt', 'rb') as f:
43 res = f.read(3)
44 print(res.decode('utf-8')) # 展示了一个字符我,证明我占三个字节
45
46 # 之前文件内指针的移动都是由读写操作被动触发的,若想读取文件某一特定位置的数据,则需要用到f.seek()方法主动控制文件内指针的移动
47 # f.seek(指针移动的字节数,模式控制)
48 # 0:默认的模式,该模式代表指针移动的字节数是以文件开头为参照的
49 # 1:该模式代表指针移动的字节数是以当前所在尾为参照的
50 #
51 # # 强调:0模式可以在t或者b中使用,1和2只能在t模式下使用
52 #
53 # # 0模式的使用的位置为参照的
54 # 2:该模式代表指针移动的字节数是以文件末尾为参照的
55
56 # 强调:0模式可以在t或者b中使用,1和2只能在b模式下使用
57
58 # 0模式的使用
59 # xxx5.txt文件内容是abc你好,abc各占一个字节,你好各占3个字节
60 # with open('xxx5.txt','rt',encoding='utf-8') as f:
61 # f.seek(2,0)
62 # print(f.tell()) # 查看当前文件的指针距离开头位置的长度,输出结果为3
63 # print(f.read()) # 指针指向了c后面,则输出你好
64
65 # t模式下会将读取的内容自动解码,所以必须保证读取的内容是一个完整的中文数据,否则解码失败
66
67 # 1模式的使用
68 with open('xxx6.txt', 'rb') as f:
69 f.seek(3, 1)
70 print(f.tell())
71 print(f.read().decode('utf-8'))
72 f.seek(3, 1)
73 print(f.tell())
74 print(f.read())
75
76 # 2模式的使用
77 with open('xxx7.txt', 'rb') as f:
78 f.seek(0, 2)
79 print(f.tell())
80 f.seek(-3, 2)
81 print(f.read().decode('utf-8'))
82
83 # 实现动态查看最新一条日志的效果
84 # 小练习:实现动态查看最新一条日志的效果
85 # import time
86 #
87 # with open('access.log', mode='rb') as f:
88 # f.seek(0, 2)
89 # while True:
90 # line = f.readline()
91 # if len(line) == 0:
92 # # 没有内容
93 # time.sleep(0.5)
94 # else:
95 # print(line.decode('utf-8'), end='')
96
97 # 文件的修改
98 # 硬盘空间是无法修改的,硬盘中数据的更新都是用新内容覆盖旧内容
99 # 内存中的数据是可以修改的
100 with open('xxx8.txt', 'r+t', encoding='utf-8') as f:
101 f.seek(9)
102 f.write('<妇女主任>')
103
104 # 文件对应的是硬盘空间,硬盘内容不能修改对应着文件内容也不可以修改,那我们看到的文件内容可以修改是怎么实现的呢?
105 # 大致的思路是:将硬盘中文件内容读入内存,在内存中修改完毕后再覆盖会硬盘
106
107
108 # 文件的修改方式1:
109 # 实现思路:将文件内容一次性全部读入内存,然后在内存中修改完毕后再覆盖写回原文件
110 # 缺点:一次性读入内存,会过多的占用内存
111 # 优点:在文件修改过程中,同一份数据只有一份
112
113 with open('xxx9.txt', 'rt', encoding='utf-8') as f:
114 res = f.read()
115
116 with open('xxx9.txt', 'wt', encoding='utf-8') as f:
117 f.write(res.replace('egon', 'alex'))
118
119
120 # 文件修改方式2:
121 # 实现思路:以读的方式打开原文件,以写的方式打开一个临时文件,一行行读取原文件内容,修改完后写入临时文件,
122 # 删掉原文件,将临时文件重命名为原文件
123 # 缺点:在文件修改的过程中同一份数据存了两份
124 # 优点:一行行读取原文件内容,不会占用太多的内存
125 import os
126 with open('db1.txt','rt',encoding='utf-8') as read_f,open('.db1.txt.temp','wt',encoding='utf-8') as write_f:
127 for line in read_f:
128 write_f.write(line.replace('egon','alex'))
129
130 os.remove('db1.txt')
131 os.rename('.db1.txt.temp','db1.txt')