一、文件操作流程

文件以什么编码存储的,就以什么编码打开

参数:

1.文件路径

2.编码方式,encode

3.执行动作(打开方式):只读,只写,追加,读写,写读…

打开一个已经存在的文件

  1. f = open('D:\qycache\飞碟说.txt',encoding='utf-8',mode='r')
  2. content = f.read()
  3. print(content)
  4. f.close()

执行输出:

知识从未如此性感

代码解释:

f 变量,可以命令为 f_obj,file,f_handler… 这个变量,称之为文件句柄(句柄是操作系统在生成对象时分配给对象的唯一标识)

open windows 的系统功能,也就是说 open 这个命令,其实就是调用系统打开文件的动作

windows 默认的编码方式:gbk,linux 默认的编码方式为 utf-8

f.close() 关闭文件

操作文件流程:

打开一个文件,产生一个文件句柄,对文件句柄进行操作,关闭文件

读:

r 只读,以 str 方式读取

rb 只读,以 bytes 类型读取(在非文字类的文件是,用 rb。比如音频文件等)

下面一个例子

  1. f = open('D:\qycache\飞碟说.txt',encoding='utf-8')
  2. content = f.read()
  3. print(content)
  4. f.close()

默认 mode 不写,表示只读模式。

编码不一致是,报错

UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xaa in position 14: illegal multibyte sequence

所以,文件以什么编码存储的,就以什么编码打开

二、文件路径

绝对路径:从根目录开始,一级一级查找知道找到文件。 比如 D:\qycache\飞碟说.txt

相对路径:在同一个文件夹下,直接写文件名即可。

相对路径举例:

  1. f = open('天气.txt',encoding='utf-8')
  2. content = f.read()
  3. print(content)
  4. f.close()

务必保证 python 代码和 txt 文件在同一文件夹下。

某些 windows 系统,读取文件的时候报错

[Error 22] Invalid argument: ‘\u202adD:\xx.txt’

解决办法:

1.加 2 个斜杠,比如 D:\xx.txt

2.前面加 r ,比如 r’D:\xx.txt’

三、文件读取的 5 种模式

r 模式有 5 种模式读取

第1种:全部读取出来 f.read()

  1. f = open('天气.txt',encoding='utf-8')
  2. content = f.read()
  3. print(content)
  4. f.close()

执行输出:

03 月 27 日(今天)

晴转多云

11~27℃

西南风 1 级

重度污染

第2种:一行一行的读 f.readline()

  1. f = open('天气.txt',encoding='utf-8')
  2. print(f.readline())
  3. print(f.readline())
  4. print(f.readline())
  5. f.close()

第3种:将原文件的每一行作为一个列表的元素 f.readlines()

  1. f = open('天气.txt',encoding='utf-8')
  2. print(f.readlines())
  3. f.close()

执行输出:

[‘03 月 27 日(今天)\n’, ‘晴转多云\n’, ‘11~27℃\n’, ‘西南风 1级\n’, ‘重度污染’]

第4种:读取一部分 f.read(n)

在 r 模式下,read(n) 按照字符去读取

  1. f = open('天气.txt',encoding='utf-8')
  2. print(f.read(3))
  3. f.close()

执行输出:

03 月

0 3 月 表示 3 个字符

第5种:for 循环读取

  1. f = open('天气.txt',encoding='utf-8')
  2. for i in f:
  3. print(i.strip())
  4. f.close()

执行输出:

03 月 27 日(今天)

晴转多云

11~27℃

西南风 1 级

重度污染

在 for 循环中,每次读取一行,结束之后,内存就释放了。所以在整个 for 循环个过程中,始终只占用了一行内容的内存。

推荐使用第 5 种方式。

四、写操作

w 文件不存在时,创建一个文件写入内容

有文件时,将原文件内容清空,再写入内容

  1. f = open('log.txt',encoding='utf-8',mode='w')
  2. f.write('人生苦短,我想学 Python')
  3. f.close()

wb 以 bytes 写入,写入的内容,必须要转换为 bytes 类型才可以

  1. f = open('log.txt',mode='wb')
  2. f.write('人生苦短,我想学 Python'.encode(encoding="utf-8"))
  3. f.close()

a 追加

没有文件时,创建一个文件追加内容

有文件时,直接追加内容

  1. f = open('log2.txt',encoding='utf-8',mode='a')
  2. f.write('666')
  3. f.close()

r+ 读写,先读,后追加。

错误的写法

  1. f = open('log.txt',encoding='utf-8',mode='r+')
  2. f.write('BBB')
  3. content = f.read()
  4. print(content)
  5. f.close()

执行输出,内容是空的

为什么呢?

因为光标,默认是从 0 开始。只要进行一个动作,光标就会移动,包括读取。

上面的代码写入时,光标移动到最后了。所以执行 f.read()时,读取不到后面的内容了。

r+ 一定要先读后写,否则会错乱或者读取不到内容

w+ 先写后读

  1. f = open('log.txt',encoding='utf-8',mode='w+')
  2. f.write('AAA')
  3. content = f.read()
  4. print(content)
  5. f.close()

执行输出,内容是空的

写完之后,光标移动到最后了。所以读取的时候,读取不到内容了。

  1. f = open('log.txt',encoding='utf-8',mode='w+')
  2. f.write('AAA')
  3. content = f.read()
  4. print(content)
  5. f.close()

执行输出:

3

AAA

下面一个例子

  1. f = open('log.txt',encoding='utf-8',mode='w+')
  2. f.write('中国')
  3. print(f.tell()) #按直接去读光标位置
  4. f.seek(2) #调整光标位置
  5. content = f.read()
  6. print(content)
  7. f.close()

执行输出:

6

…..

UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xad in position 0: invalid start byte

因为一个中文占用 3 字节

ftp 的断点续传,需要用到光标,一定会用到 tell 和 seek

a+ 追加读

这里不举例了

上面列举了那么多模式

用的最多的还是 r 和 r+模式

r 的 5 种模式中,重点掌握第 5 种。

其他操作方法:

truncate #截取文件

writable() #是否可写

readable() #是否可读

truncate 是截取文件,所以文件的打开方式必须可写,但是不能用 w 或 w+等方式打开,因为那样直接清空文件了,所以 truncate 要在 r+或 a 或 a+等模式下测试效果

  1. f = open('log.txt',encoding='utf-8',mode='r+')
  2. # 截取 10 个字节
  3. f.truncate(3)
  4. content = f.read()
  5. print(content)
  6. f.close()

执行输出:

判断是否可写

  1. f = open('log.txt',encoding='utf-8',mode='r+')
  2. print(f.writable())
  3. f.close()

执行输出:

True

回收方法为:

1、f.close() #回收操作系统级打开的文件,关闭文件句柄

2、del f #回收应用程序级的变量,在 python 代码级别中,删除变量

为了避免忘记回收文件句柄,需要使用 with open 方法,代码执行完毕之后,自动关闭文件句柄

功能 1:自动关闭文件句柄

  1. with open('log.txt',encoding='utf-8') as f:
  2. print(f.read())

功能 2:一次性操作多个文件

  1. with open('log.txt',encoding='utf-8') as f1,\
  2. open('log1.txt',encoding='utf-8',mode='r+') as f2:
  3. print(f1.read())
  4. print(f2.read())

有些情况下,必须先关闭,才能执行某某动作的情况下,不能用 with,这种情况比较少见。

推荐使用 with open

所有的软件,不是直接在原文件修改的。

它是进行了 5 步操作

1.将原文件读取到内存。

2.在内存中进行修改,形成新的内容。

3.将新的字符串写入新文件。

4.将原文件删除。

5.将新文件重命名成原文件。

将 log 文件内容中含有张三的,替换为李四

  1. import os
  2. #第 1 步
  3. with open('log',encoding='utf-8') as f1,\
  4. open('log.bak',encoding='utf-8',mode='w') as f2:
  5. content = f1.read()
  6. #第 2 步
  7. new_content = content.replace('张三','李四')
  8. #第 3 步
  9. f2.write(new_content)
  10. #第 4 步
  11. os.remove('log')
  12. #第 5 步
  13. os.rename('log.bak','log')

这种方法,不好。如果文件比较大,内存直接爆掉。因为 f1.read()是将文件所有内容写入内存中。

推荐做法:

  1. import os
  2. #第 1 步
  3. with open('log',encoding='utf-8') as f1,\
  4. open('log.bak',encoding='utf-8',mode='w') as f2:
  5. for i in f1:
  6. #第 3 步
  7. new_i = i.replace('张三', '李四')
  8. #第 4 步
  9. f2.write(new_i)
  10. #第 4 步
  11. os.remove('log')
  12. #第 5 步
  13. os.rename('log.bak','log')

这种方式,每次只占用一行。

所有软件,都是执行这 5 步的。

课后作业:

  1. 1. 文件 a.txt 内容:每一行内容分别为商品名字,价钱,个数。
  2. apple 10 3
  3. tesla 100000 1
  4. mac 3000 2
  5. lenovo 30000 3
  6. chicken 10 3
  7. 通过代码,将其构建成这种数据类型:[{'name':'apple','price':10,'amount':3},{'name':'tesla','price':1000000,'amount':1}......] 并计算出总价钱。
  8. 2,有如下文件:
  9. -------
  10. alex 是老男孩 python 发起人,创建人。
  11. alex 其实是人妖。
  12. 谁说 alex sb
  13. 你们真逗,alex 再牛逼,也掩饰不住资深屌丝的气质。
  14. ----------
  15. 将文件中所有的 alex 都替换成大写的 SB
  16. 3. 文件 a1.txt 内容:
  17. 文件内容:
  18. name:apple price:10 amount:3 year:2012
  19. name:tesla price:100000 amount:1 year:2013
  20. 通过代码,将其构建成这种数据类型:
  21. [{'name':'apple','price':10,'amount':3},
  22. {'name':'tesla','price':1000000,'amount':1}......]
  23. 并计算出总价钱。
  24. 4,文件 a2.txt 内容:
  25. 文件内容:
  26. 序号 部门 人数 平均年龄 备注
  27. 1 python 30 26 单身狗
  28. 2 Linux 26 30 没对象
  29. 3 运营部 20 24 女生多
  30. 通过代码,将其构建成这种数据类型:
  31. [{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'},
  32. ......]
  33. 并计算出总价钱。
  34. 5,明日默写:就是第二题的代码(课上讲过)。

答案:

第1题

1.1 先将文件内容读取出来

  1. with open('a.txt',encoding='utf-8') as f:
  2. for i in f:
  3. i = i.strip()
  4. print(i)

执行输出:

apple 10 3

tesla 100000 1

mac 3000 2

lenovo 30000 3

chicken 10 3

1.2 使用空格切割成列表

  1. with open('a.txt',encoding='utf-8') as f:
  2. for i in f:
  3. i = i.strip().split()
  4. print(i)

执行输出:

[‘apple’, ‘10’, ‘3’]

[‘tesla’, ‘100000’, ‘1’]

[‘mac’, ‘3000’, ‘2’]

[‘lenovo’, ‘30000’, ‘3’]

[‘chicken’, ‘10’, ‘3’]

1.3 将列表的内容放入字典中,测试打印

  1. with open('a.txt',encoding='utf-8') as f:
  2. for i in f:
  3. i = i.strip().split()
  4. print({'name': i[0], 'price': i[1], 'amount': i[2]})

执行输出:

{‘amount’: ‘3’, ‘name’: ‘apple’, ‘price’: ‘10’}

{‘amount’: ‘1’, ‘name’: ‘tesla’, ‘price’: ‘100000’}

{‘amount’: ‘2’, ‘name’: ‘mac’, ‘price’: ‘3000’}

{‘amount’: ‘3’, ‘name’: ‘lenovo’, ‘price’: ‘30000’}

{‘amount’: ‘3’, ‘name’: ‘chicken’, ‘price’: ‘10’}

1.4 将字典追加到一个空列表中

  1. #总列表
  2. li = []
  3. with open('a.txt',encoding='utf-8') as f:
  4. for i in f:
  5. #默认使用空格分割
  6. i = i.strip().split()
  7. #将字典追加到列表中
  8. li.append({'name': i[0], 'price': i[1], 'amount': i[2]})
  9. print(li)

执行输出:

[{‘price’: ‘10’, ‘name’: ‘apple’, ‘amount’: ‘3’}, {‘price’: ‘100000’, ‘name’: ‘tesla’, ‘amount’: ‘1’}, {‘price’: ‘3000’, ‘name’: ‘mac’, ‘amount’: ‘2’}, {‘price’: ‘30000’, ‘name’: ‘lenovo’, ‘amount’: ‘3’}, {‘price’: ‘10’, ‘name’: ‘chicken’, ‘amount’: ‘3’}]

1.5 计算总价格,最终完整代码如下:

  1. #总列表
  2. li = []
  3. #总价格
  4. the_sum = 0
  5. with open('a.txt',encoding='utf-8') as f:
  6. for i in f:
  7. #默认使用空格分割
  8. i = i.strip().split()
  9. #将字典追加到列表中
  10. li.append({'name': i[0], 'price': i[1], 'amount': i[2]})
  11. #遍历列表
  12. for i in li:
  13. #计算总价格(单价*个数)
  14. the_sum += int(i['price']) * int(i['amount'])
  15. print(li)
  16. print('总价钱为: {}'.format(the_sum))

执行输出:

[{‘amount’: ‘3’, ‘name’: ‘apple’, ‘price’: ‘10’}, {‘amount’: ‘1’, ‘name’: ‘tesla’, ‘price’: ‘100000’}, {‘amount’: ‘2’, ‘name’: ‘mac’, ‘price’: ‘3000’}, {‘amount’: ‘3’, ‘name’: ‘lenovo’, ‘price’: ‘30000’}, {‘amount’: ‘3’, ‘name’: ‘chicken’, ‘price’: ‘10’}]

总价钱为: 196060

老师的代码:

  1. li = []
  2. the_sum = 0
  3. name_list = ['name','price','amount','year']
  4. with open('a.txt',encoding='utf-8') as f1:
  5. for i in f1:
  6. l2 = i.strip().split()
  7. dic = {}
  8. for j in range(len(l2)):
  9. dic[name_list[j]] = l2[j]
  10. li.append(dic)
  11. #遍历列表
  12. for i in li:
  13. #计算总价格(单价*个数)
  14. the_sum += int(i['price']) * int(i['amount'])
  15. print(li)
  16. print('总价钱为: {}'.format(the_sum))

执行效果同上

第 2 题,老师讲过,直接贴代码:

  1. import os
  2. with open('log.txt',encoding='utf-8') as f1,\
  3. open('log.bak',encoding='utf-8',mode='w') as f2:
  4. for i in f1:
  5. new_i = i.replace('alex', 'SB')
  6. f2.write(new_i)
  7. os.remove('log.txt')
  8. os.rename('log.bak','log.txt')

执行代码,查看文件内容如下:

SB 是老男孩 python 发起人,创建人。

SB 其实是人妖。

谁说 SB 是 sb?

你们真逗,SB 再牛逼,也掩饰不住资深屌丝的气质。

第 3 题,和第 1 题类似

3.1 直接读取文件,并取出对应的值

  1. with open('log.txt', encoding='utf-8') as f:
  2. for i in f:
  3. # 默认使用空格分割
  4. i = i.strip().split()
  5. #使用冒号切割,获取 value
  6. name = i[0].split(':')[1]
  7. price = i[1].split(':')[1]
  8. amount = i[2].split(':')[1]
  9. year = i[3].split(':')[1]
  10. print(name,price,amount,year)

执行输出:

apple 10 3 2012

tesla 100000 1 2013

3.2 将取出的内容写入字典中,并追加到总列表里面

  1. # 总列表
  2. li = []
  3. with open('log.txt', encoding='utf-8') as f:
  4. for i in f:
  5. # 默认使用空格分割
  6. i = i.strip().split()
  7. #使用冒号切割,获取 value
  8. name = i[0].split(':')[1]
  9. price = i[1].split(':')[1]
  10. amount = i[2].split(':')[1]
  11. year = i[3].split(':')[1]
  12. #将字典追加到列表中
  13. li.append({'name':name, 'price': price, 'amount': amount,'year':year})
  14. print(li)

执行输出:

[{‘name’: ‘apple’, ‘price’: ‘10’, ‘year’: ‘2012’, ‘amount’: ‘3’}, {‘name’: ‘tesla’, ‘price’: ‘100000’, ‘year’: ‘2013’, ‘amount’: ‘1’}]

3.3 遍历总列表,计算总价钱,最终代码如下

  1. # 总列表
  2. li = []
  3. # 总价钱
  4. the_sum = 0
  5. with open('log.txt', encoding='utf-8') as f:
  6. for i in f:
  7. # 默认使用空格分割
  8. i = i.strip().split()
  9. # 使用冒号切割,获取 value
  10. name = i[0].split(':')[1]
  11. price = i[1].split(':')[1]
  12. amount = i[2].split(':')[1]
  13. year = i[3].split(':')[1]
  14. # 将字典追加到列表中
  15. li.append({'name': name, 'price': price, 'amount': amount, 'year': year})
  16. # 遍历总列表
  17. for i in li:
  18. # 计算总价钱(单价*个数)
  19. the_sum += int(i['price']) * int(i['amount'])
  20. print(li)
  21. print('总价钱为: {}'.format(the_sum))

执行输出:

[{‘year’: ‘2012’, ‘amount’: ‘3’, ‘price’: ‘10’, ‘name’: ‘apple’}, {‘year’: ‘2013’, ‘amount’: ‘1’, ‘price’: ‘100000’, ‘name’: ‘tesla’}]

总价钱为: 100030

老师的代码:可扩展性强,不论是横排还是竖排增加数据,都是适用

  1. l1 = []
  2. the_sum = 0
  3. with open('a1.txt',encoding='utf-8') as f1:
  4. for i in f1:
  5. li = i.strip().split()
  6. dic = {}
  7. for j in li:
  8. #使用冒号切割字符串,转成列表
  9. l2 = j.strip().split(':')
  10. #添加字典,l2[0]表示 key,l2[1] 表示 value
  11. dic[l2[0]] = l2[1]
  12. #将字典追加到列表中
  13. l1.append(dic)
  14. # 遍历总列表
  15. for i in l1:
  16. # 计算总价钱(单价*个数)
  17. the_sum += int(i['price']) * int(i['amount'])
  18. print(l1)
  19. print('总价钱为: {}'.format(the_sum))

执行输出,效果同上。

第 4 题

4.1 先读取文件内容

  1. with open('log.txt', encoding='utf-8') as f:
  2. for i in f:
  3. i = i.strip()
  4. print(i)

执行输出:

序号 部门 人数 平均年龄 备注

1 python 30 26 单身狗

2 Linux 26 30 没对象

3 运营部 20 24 女生多

4.2 我需要第一行内容(序号 部门 人数 平均年龄 备注),作为标题栏,放入列表中

  1. #行数
  2. line_num = 0
  3. with open('log.txt', encoding='utf-8') as f:
  4. for i in f:
  5. i = i.strip()
  6. #行数加 1
  7. line_num += 1
  8. #判断行数是否等于 1
  9. if (line_num == 1):
  10. #去除空格,使用空格切割
  11. title = i.strip().split()
  12. #加入标题的列表中
  13. title_bar = [title[0],title[1],title[2],title[3],title[4]]
  14. print(title_bar)

执行输出:

[‘序号’, ‘部门’, ‘人数’, ‘平均年龄’, ‘备注’]

4.3 将(序号 部门 人数 平均年龄 备注)里面的内容提取出来

  1. line_num += 1
  2. #判断行数是否等于 1
  3. if (line_num == 1):
  4. #去除空格,使用空格切割
  5. title = i.strip().split()
  6. #加入标题的列表中
  7. title_bar = [title[0],title[1],title[2],title[3],title[4]]
  8. else:
  9. #切割数据
  10. split_data = i.strip().split()
  11. #序号
  12. id = split_data[0]
  13. #部门
  14. department = split_data[1]
  15. #人数
  16. number = split_data[2]
  17. #平均年龄
  18. average_age = split_data[3]
  19. #备注
  20. remarks = split_data[4]
  21. #打印结果
  22. print(id,department,number,average_age,remarks)

执行输出:

1 python 30 26 单身狗

2 Linux 26 30 没对象

3 运营部 20 24 女生多

4.4 将最后一行代码 print 改成字典输出

  1. #行数
  2. line_num = 0
  3. li = []
  4. with open('log.txt', encoding='utf-8') as f:
  5. for i in f:
  6. i = i.strip()
  7. #行数加 1
  8. line_num += 1
  9. #判断行数是否等于 1
  10. if (line_num == 1):
  11. #去除空格,使用空格切割
  12. title = i.strip().split()
  13. #加入标题的列表中
  14. title_bar = [title[0],title[1],title[2],title[3],title[4]]
  15. else:
  16. #切割数据
  17. split_data = i.strip().split()
  18. #序号
  19. id = split_data[0]
  20. #部门
  21. department = split_data[1]
  22. #人数
  23. number = split_data[2]
  24. #平均年龄
  25. average_age = split_data[3]
  26. #备注
  27. remarks = split_data[4]
  28. #打印结果
  29. print({title_bar[0]:id,title_bar[1]:department,title_bar[2]:number,title_bar[3]:average_age,title_bar[4]:remarks})

执行输出:

{‘人数’: ‘30’, ‘备注’: ‘单身狗’, ‘序号’: ‘1’, ‘平均年龄’: ‘26’, ‘部门’: ‘python’}

{‘人数’: ‘26’, ‘备注’: ‘没对象’, ‘序号’: ‘2’, ‘平均年龄’: ‘30’, ‘部门’: ‘Linux’}

{‘人数’: ‘20’, ‘备注’: ‘女生多’, ‘序号’: ‘3’, ‘平均年龄’: ‘24’, ‘部门’: ‘运营部’}

4.5 将打印的字典,添加到总列表中,最终代码如下

  1. #行数
  2. line_num = 0
  3. #总列表
  4. li = []
  5. with open('log.txt', encoding='utf-8') as f:
  6. for i in f:
  7. i = i.strip()
  8. #行数加 1
  9. line_num += 1
  10. #判断行数是否等于 1
  11. if (line_num == 1):
  12. #去除空格,使用空格切割
  13. title = i.strip().split()
  14. #加入标题的列表中
  15. title_bar = [title[0],title[1],title[2],title[3],title[4]]
  16. else:
  17. #切割数据
  18. split_data = i.strip().split()
  19. #序号
  20. id = split_data[0]
  21. #部门
  22. department = split_data[1]
  23. #人数
  24. number = split_data[2]
  25. #平均年龄
  26. average_age = split_data[3]
  27. #备注
  28. remarks = split_data[4]
  29. #将字典添加到列表中
  30. li.append({title_bar[0]:id,title_bar[1]:department,title_bar[2]:number,title_bar[3]:average_age,title_bar[4]:remarks})
  31. print(li)

执行输出:

[{‘备注’: ‘单身狗’, ‘平均年龄’: ‘26’, ‘人数’: ‘30’, ‘序号’: ‘1’, ‘部门’: ‘python’}, {‘备注’: ‘没对象’, ‘平均年龄’: ‘30’, ‘人数’: ‘26’, ‘序号’: ‘2’, ‘部门’: ‘Linux’}, {‘备注’: ‘女生多’, ‘平均年龄’: ‘24’, ‘人数’: ‘20’, ‘序号’: ‘3’, ‘部门’: ‘运营部’}]

老师的代码:可扩展性强,不论是横排还是竖排增加数据,都是适用

  1. l1 = []
  2. with open('a2.txt',encoding='utf-8') as f1:
  3. #读取第一行,去除空格,使用空格切割成列表
  4. list_name = f1.readline().strip().split()
  5. #从第二行开始读取,因为读取一行之后,光标自动移动到下面一行。
  6. #所以 for 循环不会读取到第一行
  7. for i in f1:
  8. dic = {}
  9. #去除空格,以空格切割成列表
  10. i = i.strip().split()
  11. #遍历 i
  12. for j in range(len(i)):
  13. #添加字典, list_name[j]表示 key, i[j]表示 value,比如'序号': '1'
  14. dic[list_name[j]] = i[j]
  15. #添加到列表中
  16. l1.append(dic)
  17. print(l1)

执行效果同上