抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

image-20210617001955989

第十三章 文件

13.1 计算机眼中的文件

任务一:文件的概念和作用

知识点:

计算机的文件,就是存储在某种长期储存设备上的一段数据

存储设备包括:硬盘、U 盘、移动硬盘、光盘…

文件的作用:将数据长期保存下来,在需要的时候使用

任务二:计算机的文件储存方式

知识点:

在计算机中,文件是以二进制的方式保存在磁盘上的

文本文件

可以使用文本编辑软件查看内容,本质上还是二进制文件

例如:python 的源程序

二进制文件

保存的内容不是给人直接阅读的,而提供给计算机其他程序使用的

例如:图片文件、音频文件、视频文件等等

二进制文件不能使用文本编辑软件查看

任务三:在控制台中查看文件内容

知识点:

在Windows中,控制台指令type查看文件内容

在Linux或Mac中,控制台指令cat查看文件内容

在Jupyter中,cell中输入指令**%pycat**查看文件内容

中文字符可能会在控制台中乱码

13.2 文件操作

13.2.1 基本流程

任务一:文件操作的基本流程

知识点:在计算机中要操作文件方式是非常固定,共包含三个步骤

1、打开文件

2、读或写文件

将文件内容读入内存

将内存内容写入文件

3、关闭文件

任务二:操作文件的基本流程

Python 中要操作文件需要记住1个函数和3个文件方法

open 函数负责打开文件,并且返回文件对象

read/write/close 三个方法都需要通过文件对象来调用

函数/方法 说明
open 打开文件,并且返回文件操作对象
read 将文件内容读取到内存
write 将指定内容写入文件
close 关闭文件

知识点:文件操作的常用流程

调用**open()**函数打开要操作的文件

调用文件方法**read()write()**方法对文件进行读写操作

调用**close()**方法关闭文件,释放资源

13.2.2 文件的open()函数与close()方法

任务一:open()函数用法

知识点:

语法:open(name[, mode, encoding])

描述:open()函数用于打开一个文件名为name的文件

如果文件存在,返回一个file类型的对象,后续通过该对象进行文件的读写操作

如果文件不存在,会抛出异常

参数:name为包含相对路径或绝对路径的文件名

文件名区分大小写

由于路径中会包含\字符,与转移标识符冲突。为此,需要使用r字符串前缀,告知Python当前字符串不进行转义

返回:file类型的对象fileObject,用于后续的文件读写操作

例子:相对路径和绝对路径的文件打开方式

在当前目录下创建一个名为README.txt文件

文件中输入几行字符串,然后保存关闭

1
2
3
4
5
# 相对路径,打开当前根目录文件
f = open("README.txt")

# 绝对路径,字符串前的r表示直接使用字符\而非转义字符
f = open(r"D:\README.txt")

任务二:open()函数的可选参数

知识点:

参数:mode可选,指定文件打开模式(后续将给出详解)。默认以只读模式打开

参数:encoding关键字参数,可选,指定文件编码方式

对于中文文件,如果编码不匹配,会造成乱码

目前国际上最通用的是**’utf-8’编码。因此,可以设置文件打开的编码为encoding=’utf-8’**

1
2
3
4
# 使用默认只读"r"、'utf-8'编码打开"README.txt"
# 返回文件对象为f
f = open("README.txt", encoding='utf-8')
print(type(f))

*任务三:文件的关闭**close()*方法

知识点:关闭文件**close()**方法

语法:fileObject.close()

描述:**close()**方法用于关闭一个已打开的文件

关闭后的文件不能再进行读写操作,否则会触发ValueError异常

当文件不再需要使用时,用 **close()**方法关闭文件释放资源是一个好的习惯

参数和返回:无

注意:如果忘记关闭文件,会造成系统资源消耗,而且会影响到后续对文件的访问

1
2
3
4
# 关闭的文件对象必须要在内存中存在,否则会出错
f = open("README.txt")
# 文件不再使用,释放资源
f.close()

任务四:3种自定义文件路径方式(重要)

知识点:

本地文件的访问需要指定路径。如果文件不在当前目录下,就需要明确文件的详细路径

由于常用的路径使用\来标识路径的层级关系,但是这与\转移字符的标识冲突。为此,提供了三种解决方案

单个反斜杠:/

两个斜杠:\(第一个\是转义符)

r用于防止字符转义

1
2
3
4
5
6
7
8
9
10
11
12
# 本地文件的界定:指向一个本地存储的文件,是一个链接或者一个映射
# 单个反斜杠:/
path1 = 'C:/Users/Hjx/Desktop/text.txt'
# 两个斜杠:\\(第一个\是转义符)
path2 = 'C:\\Users\\Hjx\\Desktop\\text.txt'
# r用于防止字符转义
path3 = r'C:\Users\Hjx\Desktop\text.txt'

# 输出文件路径
print(path1)
print(path2)
print(path3)

扩展:任何文件都可以使用鼠标右键->属性来查看具体文件的绝对路径

13.2.3 open()函数配置读写模式

任务一:文件的打开模式

知识点:

open()函数默认以只读方式打开文件,并且返回文件类型的对象

Python通过open()函数mode参数对文件的操作提供了丰富的控制模式

语法如下:

1
f = open("文件名", "访问mode")

任务二:6种文件读写模式

知识点:open()函数mode参数解析

r只读模式打开文件,增强型 r+可读写模式打开文件

文件的指针将会放在文件的开头

需要该文件必须存在,否则会出错

例如:f = open(“README.txt”, “r”)

w只写模式打开文件,增强型w+可读写模式打开文件

若文件存在则原内容会被清空

若文件不存在则建立该文件

例如:f = open(“README.txt”, “w”)

a追加只写模式打开文件,增强型a+追加可读写模式打开文件

如果该文件已存在,文件指针将会放在文件的结尾

如果文件不存在,新建文件进行写入

例如:f = open(“README.txt”, “a”)

注意:

频繁的移动文件指针,会影响文件的读写效率

开发中更多的时候会以只读、只写的方式来操作文件

任务三:文件对象的属性

知识点:文件对象的3个属性

fileObject.closed:返回True如果文件已被关闭,否则返回False

fileObject.mode:返回被打开文件的访问模式

fileObject.name:返回文件的名称

1
2
3
4
5
f = open("README.txt")
print(f'.closed: {f.closed}')
print(f'.mode: {f.mode}')
print(f'.name: {f.name}')
f.close()

13.2.4 文件的读方法

任务一:文件的读方法

知识点:

语法:fileObject.read(size)

描述:read()从文件中一次性读入返回文件的所有内容

参数:size为非负整数,可选

指定读取文件的字节数,包括 **”\n”**字符

默认值,尝试尽可能多地读取文件内容,甚至读取当前整个文件内容

返回:从文件中读取的字符串

注意read()方法执行后,会把文件指针移动到文件的末尾

例子:文件读程序

首先在当前目录下手动创建一个名为README.txt的文本文件,里面随意写几行内容并保存关闭

然后使用**read()**读取文件

1
2
3
4
5
6
7
8
9
# 1. 打开 - 文件名需要注意大小写
file = open("README.txt")

# 2. 读取
text = file.read()
print(text)

# 3. 关闭
file.close()

注意:在开发中,通常会先编写打开关闭的代码,再编写中间针对文件的读/写 操作!

任务二:文件指针

知识点:

文件指针并非C语言里的指针

文件指针标记从文件的哪个位置开始读写数据

第一次打开文件时,通常文件指针会指向文件的开始位置

当执行了read()方法后,文件指针会随着读取的内容进行移动

对于当前文件对象,文件指针具有记忆性

即下次再次调用read()方法会从上次读取内容之后开始

默认情况下会移动到文件末尾,除非指定read()方法的size参数

思考:

如果执行了一次**read()**方法,读取了所有内容,那么再次调用 **read()**方法,还能够获得到内容吗

答案:不能。第一次读取之后,文件指针移动到了文件末尾,再次调用不会读取到任何的内容

13.2.5 按行读取文件

任务一:按行读取文件

需求分析:

read()方法默认会把文件的所有内容一次性读取到内存中

如果文件太大,对内存消耗会非常严重

知识点:

语法:fileObject.readline()

描述:**readline()**方法一次读取文件的一行内容

参数:无

返回:返回从文件当前行中读取的字符串

注意:该方法执行后,会把文件指针移动到下一行,准备下次读取。依次读取所有行,直到文件结束符 EOF

例子:大文件读取方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 打开文件
file = open("README.txt")

while True:
# 读取一行内容
text = file.readline()
# 判断是否读到内容
if not text:
break
# 每读取一行的末尾已经有了一个 `\n`
print(text, end="")

# 关闭文件
file.close()

实例:爬取POI数据并转换为JSON格式

需求:

利用百度POI小插件爬取一些POI数据,然后存成txt文档

再用Python读取,编写成一个json格式(列表嵌套字典):**[{‘name’:’…’,’lng’:…,’lat’:…,’address’:’…’},{…},…,]**

第一步:爬取数据地址:https://www.metrodata.cn/poi 。输入地区和关键字,稍等几分钟就会出现爬取的数据。可以自定义查询参数

第二步:使用Python将数据转换为JSON格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
f = open('shaoxian.txt','r')  # 读取txt文件
m = [] # 新建一个空列表,用于存储数据
n = 0

for line in f.readlines():
n += 1
st1 = line.split(':')
name = st1[0] # 先以:拆分,筛选出name文本
information = st1[1] # 第二部分包括lng,lat,address
st2 = information.split(',')
lng = float(st2[0]) # 筛选出lng
lat = float(st2[1]) # 筛选出lat
ad = st2[2].strip() # 筛选出address,去除末尾空格
# 做成嵌套列表
data = [['name',name],['lng',lng],['lat',lat],['address',ad]]
m.append(dict(data)) # 生成字典,并追加如列表m
#print('成功转换%i个数据'%n)

print(m)
print('\n数据转换完成!总共转换%i个数据'%n)

13.2.6 文件的写方法

任务一:文件写方法write()

知识点:

语法:fileObject.write(str)

描述:**write()**方法用于向文件中写入指定字符串

参数:str为向文件写入指定的字符串

返回:返回的是写入的字符长度

注意:write()方法不会向字符串尾部自定添加换行符,需要手动添加**”\n”**

例子:文件写操作

1
2
3
4
5
6
7
8
# 需要以写模式"w"打开文件
f = open("README.txt", "w")

f.write("hello python!\n")
f.write("今天天气真好")

# 关闭文件
f.close()

任务二:将列表写入文件

通过**writelines()**函数,将列表作为参数,写入文件

1
2
3
4
5
6
7
# 当前目录
f = open('test_write.txt', 'w', encoding = 'utf8')
lst = ['a','b','c','d','e']
f.writelines(lst)
f.close()
# f.writelines(list):依次把列表元素写入,但这里有没有换行?
# 如果想每一个元素换行怎么办?每个元素后都有"\n"

通过遍历为列表的每个元素添加换行符,考虑列表推导式方式

1
2
3
4
5
6
7
8
9
f = open('test_write2.txt', 'w', encoding = 'utf8')
lst = ['a','b','c','d','e']

for i in range(len(lst)):
lst[i] = lst[i] + '\n'

f.writelines(lst)
f.close()
# 通过遍历给每个元素最后加上"\n"

13.2.7 (重要) with as语句维护文件操作环境

需求分析:

任何一门编程语言中,文件的输入输出、数据库的连接断开等,都是很常见的资源管理操作。但资源都是有限的,在写程序时,必须保证这些资源在使用过后得到释放,不然就容易造成资源泄露,轻者使得系统处理缓慢,严重时会使系统崩溃

例如,前面在介绍文件操作时,一直强调打开的文件最后一定要关闭,否则会程序的运行造成意想不到的隐患

但是,即便使用close()做好了关闭文件的操作,如果在打开文件或文件操作过程中抛出了异常,还是无法及时关闭文件

知识点:

在Python中,对应的解决方式是使用 with as 语句操作上下文管理器(context manager),它能够帮助我们自动分配并且释放资源

通过使用 with as 语句,打开的文件对象,无论期间是否抛出异常,都能保证with as语句执行完毕后自动调用**close()**方法

知识点:with as 语句的基本语法格式为:

1
2
with 表达式 as obj:
代码块

表达式:可以是资源打开函数的返回对象。比如文件**open()**函数,数据库连接函数等

obj:资源对象。比如文件**open()**函数返回的文件对象

将下面的代码改为为with…as语句

1
2
3
4
5
6
7
8
# 需要以写模式"w"打开文件
f = open("README.txt", "w")

f.write("hello python!\n")
f.write("今天天气真好")

# 关闭文件
f.close()

有时候不得不承认Python编程就是一种享受,只要掌握该语言的某些特性

1
2
3
4
5
6
# 将open()函数的返回值通过as赋值给f文件对象
with open("README.txt", "w") as f:
f.write("hello python!\n")
f.write("今天天气真好")

# 退出with作用域(语句块),f对象自动销毁

13.3 综合实例

13.3.1 实例:文件指针问题

下面程序功能,打开一个文件,然后先向文件**write()写入字符串,然后再read()**读取字符串,并输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 请换一个文件名,"w+"为读写模式
f = open("Data.txt", "w+", encoding='utf-8')
# 手动添加换行符\n
data_str = "hello python\n"

# 写3行data_str
f.write(data_str)
f.write(data_str)
f.write(data_str)

file_str = f.read()
print(file_str)

f.close()

程序解析:

**f = open(“Data.txt”, “w+”, encoding=’utf-8’),以增强型“w+”读写方式、‘utf-8’编码打开文件“Data.txt”,由于该文件不存在,所以“Data.txt”**文件会被创建

调用3次写文件**f.write(data_str)**方法,在文件中写入3行字符串

然后,再调用读文件**f.read()方法,希望读取之前写入的内容。但是发现,读取内容为空。但是打开“Data.txt”**后,发现字符串已经被写入到文件中

原因分析

当写文件完成时,文件的当前文件指针会处于文件末尾处

如果继续执行读取操作,系统从该光标处向后读取,但该文件指针已处于文件的末尾,所以读出内容为空

解决方法一:规范代码,将写文件和读文件分开。在执行完一个操作后应及时关闭文件对象**f.close()**。使用这种方法可以是文件安全有效,不会被其他操作影响预计效果

1
2
3
4
5
6
7
8
9
10
11
12
f = open("Data.txt", "w+", encoding='utf-8')
data_str = "hello python\n"
f.write(data_str)
f.write(data_str)
f.write(data_str)
f.close() #关闭文件

# 重新打开文件,文件指针回到文件开始
f = open("Data.txt", "r+", encoding='utf-8')
file_str = f.read()
print(file_str)
f.close()

或者使用文件的逐行遍历

1
2
3
4
5
f = open("Data.txt", "r+", encoding='utf-8')
for line in f.readlines():
print(line, end = '')

f.close()

解决方法二:使用**seek()**方法移动光标至指定位置

知识点:文件光标移动

语法:fileObject.seek(offset,whence=0)

参数:offset为偏移量,即需要移动偏移的字节数

参数:whence为要从哪个位置开始偏移,默认值为0;0代表从文件开始为起始点,1代表从当前位置为起始点,2代表从文件末尾为起始点

1
2
3
4
5
6
7
8
9
10
11
12
13
f = open("Data.txt", "w+", encoding='utf-8')
data_str = "hello python\n"
f.write(data_str)
f.write(data_str)
f.write(data_str)

# offset= 0,whence=0
# 从文件开始,以偏移量为0设置光标。
f.seek(0,0)

file_str = f.read()
print(file_str)
f.close()

习题:

将上面文件操作程序修改为with as语句结构

1
2
3
4
5
6
7
8
with open("Data.txt", "w+", encoding='utf-8') as f:
data_str = "hello python\n"
f.write(data_str)
f.write(data_str)
f.write(data_str)
f.seek(0,0)
file_str = f.read()
print(file_str)

13.3.2 实例:文件数据的数值求和

需求分析:

while循环章节中,所有平均值计算程序都有一个缺点:数字都需要用户手动输入。试想用户正在尝试着求100个数字的平均值,而恰巧在接近尾声时发生了打字错误。如果用户使用上面编写的程序,就需要从头开始,想想就崩溃

为此,解决该问题的一个可行方法是首先将所有数字都输入到文件中,即使用户在文件中输错了数字,也可以很轻易地进行修改和编辑

因此,需要将之前设计的平均值计算程序从用户输入数据改写为从文件中读取数据

这种面向文件的程序数据处理方式在现实应用中非常常见

本节将学习如何从文件中读取数据,然后实现哨兵式循环来计算平均数

任务一:数据生成

创建一个数据文件,共100行,每一行为一个随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import random as rd

# 例如:Data.txt
name = input('请输入文件名: ')
f = open(name, "w+", encoding='utf-8')

for i in range(100):
# 随机生成[-10,10]区间的整数
num = rd.randint(-10, 10)
# 将num转换为字符串,与换行符'\n'拼接,写入文件中
f.write(str(num) + '\n')

print(f'生成结束,请打开{name}查看结果')
f.close()

任务二:while哨兵式循环来计算平均值

下面将对文件中的数字进行求平均,使用文件结束符EOF或空字符**””**作为循环的哨兵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 输入之前生成数字的文件:Data.txt
fileName = input("输入文件名: ")
infile = open(fileName,'r', encoding='utf-8')

total = 0.0
count = 0

# 从文件中先读一行
line = infile.readline()

# 将line为空作为哨兵,即读到文件末尾
while line != "":
total += float(line)
count += 1
line = infile.readline()

print("平均值为:", total / count)
f.close()

任务三:for循环来计算平均值

相对于其他语言,Python提供了简便的文件读取方式,使用**readlines()**方法读取整个文件,返回以行为元素的列表。然后,通过for循环遍历元素(行),并对其做运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 输入之前生成数字的文件:Data.txt
fileName = input("输入文件名: ")
infile = open(fileName,'r', encoding='utf-8')

total = 0.0
# 将文件按行读,返回列表
lines = infile.readlines()

# 再用for循环遍历列表元素
for line in lines:
total = total + float(line)

print("平均值为:", total / len(lines))
f.close()

程序解析:

显然,for循环比while循环更简洁

这程序for循环之所以能用,是因为Python提供了readlines()方法将整个文件以行为元素,返回列表。然后,就可以使用Python的确定循环(for循环),来遍历和处理列表元素

对于非Python语言,并不一定提供readlines()这么方便的方法。因此,只能通过哨兵式的while循环,进行文件读和相关运算

习题

将上面文件操作程序修改为with as语句结构

1
2
3
4
5
6
7
import random as rd
name = input('请输入文件名: ')
with open(name, "w+", encoding='utf-8') as f:
for i in range(100):
num = rd.randint(-10, 10)
f.write(str(num) + '\n')
print(f'生成结束,请打开{name}查看结果')

13.3.3 实例:复制文件

任务一:小文件复制

打开一个已有文件,读取完整内容,并写入到另外一个文件

1
2
3
4
5
6
7
8
9
10
11
# 1. 打开文件
file_read = open("README")
file_write = open("README[复件]", "w")

# 2. 读取并写入文件
text = file_read.read()
file_write.write(text)

# 3. 关闭文件
file_read.close()
file_write.close()

任务二:大文件复制

打开一个已有文件,逐行读取内容,并顺序写入到另外一个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 打开文件
file_read = open("README")
file_write = open("README[复件]", "w")

# 2. 读取并写入文件
while True:
# 每次读取一行
text = file_read.readline()

# 判断是否读取到内容
if not text:
break

file_write.write(text)

# 3. 关闭文件
file_read.close()
file_write.close()

13.4 (常识) 文件和目录管理操作

13.4.1 常用文件和目录函数介绍

知识点:

控制台终端文件系统中可以执行常规的文件/目录管理操作,例如:创建、重命名、删除、改变路径、查看目录内容等

Python中,实现上述功能需要导入 os 模块

注意:

Jupyter的cell支持IPython的文件和目录管理指令

文件查询命令:**%ls**

显示文件内容:**%cat**

任务三:文件操作

方法名 说明 示例
rename 重命名文件 os.rename(源文件名, 目标文件名)
remove 删除文件 os.remove(文件名)

任务四:目录操作

方法名 说明 示例
listdir 目录列表 os.listdir(目录名)
mkdir 创建目录 os.mkdir(目录名)
rmdir 删除目录 os.rmdir(目录名)
getcwd 获取当前目录 os.getcwd()
chdir 修改工作目录 os.chdir(目标目录)
path.isdir 判断是否是文件 os.path.isdir(文件路径)

13.4.2 相对路径和绝对路径

任务一:当前目录

知识点:什么是当前工作目录?

每个运行在计算机上的程序,都有一个“当前工作目录”( cwd)

使用**os.getcwd()**函数取得当前工作路径

使用os.chdir() 切换当前目录,类似控制台的cd指令

1
2
3
4
5
6
7
8
9
# 导入os模块
import os

# 获得当前目录
print(os.getcwd())

# 切换当前目录
os.chdir('C:\Windows\System32')
print(os.getcwd())

注意:

如果使用os.chdir()修改当前目录,当指定目录不存在时,Python 解释器触发异常FileNotFoundError

例如,os.chdir(‘C:\error’),假设error目录不存在

任务二:相对路径和绝对路径 (重要)

知识点:明确一个文件所在的路径,有 2 种表示方式,分别是:

绝对路径:总是从根文件夹开始

Window 系统中以盘符(C:D:)作为根文件夹

Mac或Linux系统中以**/**作为根文件夹

相对路径:指的是文件相对于当前工作目录所在的位置

例如,当前工作目录为”C:\Windows\System32”,若文件 demo.txt 就位于这个 System32 文件夹下,则demo.txt的相对路径表示为 “.\demo.txt”

其中 .\ 就表示当前所在目录

知识点(常识):常用的相对路径表示

.\ 表示当前所在目录。例如 .\data.txt,表示当前文件夹data.txt文件

..\ 表示当前所在目录的父目录。例如 ..\data.txt,表示父文件夹中的data.txt文件

任务三:os.path模块

知识点:Python os.path 模块提供了一些函数,可以实现绝对路径和相对路径之间的转换,以及检查给定的路径是否为绝对路径,例如:

调用 os.path.abspath(path) 将返回 path 参数的绝对路径的字符串,这是将相对路径转换为绝对路径的简便方法

调用 **os.path.isabs(path)**,如果参数是一个绝对路径,就返回 True,如果参数是一个相对路径,就返回 False

调用 os.path.relpath(path, start) 将返回从 start 路径到 path 的相对路径的字符串。如果没有提供 start,就使用当前工作目录作为开始路径

调用 os.path.dirname(path) 将返回一个字符串,表示文件夹路径。它包含 path 参数中最后一个斜杠之前的所有内容

调用 os.path.basename(path) 将返回一个字符串,表示文件名。它包含 path 参数中最后一个斜杠之后的所有内容

注意:例子中的路径可以根据实际情况自定义,不必要完全遵照本节的例子,根据自己的系统环境对本节代码做适当调整即可

1
2
3
4
5
6
7
8
9
10
11
# 获得当前路径
print(os.getcwd())

# 获得当前路径的绝对路径
print(os.path.abspath('.'))

# 获得相对路径'.\Scripts'的的绝对路径
print(os.path.abspath('.\Scripts'))

# 测试当前path是否为绝对路径,输出False
print(os.path.abspath('.'))
1
2
3
4
5
6
7
8
9
10
11
12
# os.path.abspath('.')获得绝对路径
# 然后作为实参传递给os.path.isabs()函数
# 输出为True
print(os.path.isabs(os.path.abspath('.')))

# 从'C:\'开始,到'C:\Windows'的相对路径
# 输出为'Windows',结合截图来理解
print(os.path.relpath('C:\Windows', 'C:\'))

# 从'C:\spam\eggs'开始,到'C:\Windows'的相对路径
# 输出为'..\..\Windows',结合截图来理解
print(os.path.relpath('C:\Windows', 'C:\spam\eggs'))
1
2
3
4
5
6
# 获得文件名(不含路径),输出为'calc.exe'
path = 'C:\Windows\System32\calc.exe'
print(os.path.basename(path))

# 获得路径名(不含文件)
print(os.path.dirname(path))

13.4.3 实例:文件目录操作

例子中的文件路径都需要根据具体文件位置进行自定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# os模块:系统模块 - 常用命令
import os # 导入模块
# 输出字符串指示正在使用的平台。
# 如果是window 则用'nt'表示
# 对Linux/Unix用户,它是'posix'。
print(os.name)
# 函数得到当前工作目录,即当前Python脚本工作的目录路径。
print(os.getcwd())
# 返回指定目录下的所有文件和目录名。
print(os.listdir())

# 切换到目标路径
#os.chdir('C:\\Users\\Hjx\\Desktop\\' )
#print(os.getcwd())

# 删除一个文件
#os.remove('text2.txt')

# 函数返回一个路径的目录名和文件名
print(os.path.split('C:\\Users\\Hjx\\Desktop\\text.txt'))

# 用来检验给出的路径是否真地存在
# 这里不存在改文件故False,但路径存在故True
print(os.path.exists('C:\\Users\\Hjx\\Desktop\\heheh.txt'))
print(os.path.exists('C:\\Users\\Hjx\\Desktop\\'))

13.5 (常识) UTF-8编码解决中文乱码问题

知识点:文本文件存储的内容是基于字符编码的文件,常见的编码有 ASCII 编码,UNICODE 编码等

Python 2默认使用 ASCII 编码格式

Python 3默认使用 UTF-8 编码格式

如果文件网络爬虫数据中包含非 ASCII 编码字符,首先要将字符转换为 UTF-8 编码,才能被不会出现乱码问题

任务一:ASCII 编码和 UTF-8 编码

知识点:ASCII 编码

计算机中只有 256ASCII 字符。

一个 ASCII 在内存中占用 1 个字节 的空间。

80/1 的排列组合方式一共有 256 种,也就是 2 ** 8

对于中文如果使用ASCII 码,将会出现乱码

知识点:UTF-8 编码格式

计算机中使用 1~6 个字节来表示一个UTF-8字符,涵盖了地球上几乎所有地区的文字

大多数汉字会使用3 个字节表示

UTF-8UNICODE编码的一种编码格式

任务二:使用UTF-8 编码防止中文乱码

虽然Python 3.x默认使用 UTF-8 编码格式,但是对于中文文件也会出现乱码问题,特别是读取包含中文的文本

知识点:建议在源文件的第一行增加以下代码,解释器会以 utf-8 编码来处理 python文件

1
2
3
#在源文件的第一行增加以下代码(二选一)
# *-* coding:utf8 *-*
# coding=utf8

在读取包含中文文件时,**open()**函数指定encoding参数为 utf-8 。例如:

1
2
3
4
5
f = open("Data.txt", "r+", encoding='utf-8')
for line in f.readlines():
print(line, end = '')

f.close()

任务三:使用UTF-8编码字符串

知识点:

Python 2 中,即使指定了文件使用 UTF-8 的编码格式,但是在遍历字符串时,仍然会以字节为单位遍历字符串

要能够正确的遍历字符串,在定义字符串时,需要在字符串的引号前,增加一个小写字母 u,告诉解释器这是一个 unicode 字符串

虽然Python 3的字符串都使用 UTF-8编码,但是如果字符串来自文件网络爬虫数据(可能不是使用UTF-8),需要将它们先转换为UTF-8,程序才不会出现乱码问题

1
2
3
4
5
6
7
8
9
# *-* coding:utf8 *-*

# 在字符串前,增加一个 `u` 表示这个字符串是一个 utf8 字符串
hello_str = u"你好世界"

print(hello_str)

for c in hello_str:
print(c)

评论