python自动化测试 第 5 章.文件操作

一、文件概述

1. 什么是文件

计算机文件是一个存储在存储器上的数据的序列,可以包含任意的数据内容。

  • 文本文件 有统一的字符编码
  • 二进制文件 字符编码不统一(如:图片、视频文件等)

2. 字符编码

一个一个的小图片,字体文件 包含了这个字体类型的所有文字的图片。再给每个字符一个编号,
存储的时候,存这个编号。这个编号标就是字符编码。

2.1 ascii码

在计算机中,所有的数据在存储和运算时都要使用二进制数表示(因为计算机用高电平和低电平分别表示1和0),例如,像a、b、c、d这样的52个字母(包括大写)以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用二进制数来表示,而具体用哪些二进制数字表示哪个符号,当然每个人都可以约定自己的一套(这就叫编码),而大家如果要想互相通信而不造成混乱,那么大家就必须使用相同的编码规则,于是美国有关的标准化组织就出台了ASCII编码,统一规定了上述常用符号用哪些二进制数来表示
ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符

image.png

1Byte = 8bit
1Kb = 1024B
1Mb = 1024Kb
1Gb = 1024Mb
1Tb = 1024Gb
一个字节 = 8位 8位二进制 0-255
一个ASCII码占用存储空间为1个字节
10000个ASCII码占用的内存大小为:10000 /1024 Kb

2.2 gb2312

ASCII不支持中文,为了支持计算机使用中文,推出gb2312.

GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312。
基本集共收入汉字6763个和非汉字图形字符682个。

0-6763

2个字节来表示一个汉字

10000个中文所占的内存大小:10000*2B/1024

向上兼容ascii

2.3 gbk

GBK是GB2312的扩展,因为GB2312有些生僻字无法识别,所以开发了GBK编码,K就是扩展的意思
GBK 采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。
2个字节表示一个汉字
向上兼容ascii

print('囙'.encode('gbk')) # 输出b'\x87\xe0'
print('囙'.encode('gb2312')) # 会报错

2.4 unicode

把世界上所有主流的编码都收纳进来。10w+
4个字节来表示一个字符
缺点:太大了,且内存变大
python3在内存里使用unicode

2.5 utf-8

根据字符编号动态的选择大小。
ascii 1个字节
中文 3个字节
UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是针对Unicode的一种可变长度字符编码。它可以用来表示Unicode标准中的任何字符,而且其编码中的第一个字节仍与ASCII相容,使得原来处理ASCII字符的软件无须或只进行少部分修改后,便可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。

ANSI码是指电脑用什么编码就用什么编码

3. 信息量

bit,一个位,表示一个二进制数 0,1

8bit叫一个Byte(字节)2的八次方 256

  • 1024B = 1KB
  • 1024KB = 1MB
  • 1024MB = 1GB
  • 1024GB = 1TB

0-255 之间的整数

4. 字节类型

Bytes表示二进制信息,它由单个字节构成的不可变序列。

字面量语法与字符串相似,加了一个前导符‘b’

只允许有ascii

超过了127的二进制值,使用十六进制来表示。

字符转换为对应的编码称为编码 A -> b'\x41'

根据字符编码转换为字符称为解码 b'\x41' -> A 解码

# ascii码字符编码,使用本身字母的字面量来表示。
res = 'abc123'.encode('ascii')
print(res, type(res))  # 输出b'abc123'

# gbk 用两个字节表示一个汉字,utf-8使用3个字节表示一个汉字
print('中'.encode('gbk'), type('中'.encode('gbk')))  # 输出b'\xd6\xd0'
print('中'.encode('utf-8'), type('中'.encode('utf-8')))  # 输出b'\xe4\xb8\xad'

# 解密
print(b'\xd6\xd0'.decode('gbk')) # 输出"中"
# 中‘’字在gbk编码中编码为54992
print(bin(54992))
print(hex(0b11010110))

不是所有的二进制信息都可以解码为字符。

用不一致的解码方式去打开对应的文件,会出现乱码:
notepad++打开一个记事本文件--编码--选择日文,并粘贴日文到记事本中--再使用其他编码方式,此时日文会变成乱码


image.png

二、python操作文件

    1. 打开文件
    1. 操作文件 (读 写)
    1. 关闭文件

1. open函数

open(file, mode='r', encoding=None)

mode的取值:

字符 意义
'r' 文本读取(默认)
'w' 文本写入,并先清空文件(慎用),文件不存在则创建
'x' 文本写,排它性创建,如果文件已存在则失败
'a' 文本写,如果文件存在则在末尾追加,不存在则创建

mode组合的字符

字符 意义
'b' 二进制模式,例如:'rb'表示二进制读
't' 文本模式(默认),例如:rt一般省略t
'+' 读取与写入,例如:'r+' 表示同时读写

2.读文本文件

在当前目录下创建一个名为 test.txt 的文本文件,(注意编码方式)文件中写入下面的内容:

静夜思
床前明月光,疑是地上霜。
举头望明月,低头思故乡。

2.1 操作基本步骤

# 打开文件 mode=rt,t可以省略
fb = open('test.txt', 'r', encoding='utf-8')
# 读取
content = fb.read()
print(content)
# 关闭文件
fb.close()

这种操作经常会忘记关闭文件句柄,造成资源浪费,所以处理文件是往往使用 with 语句进行上下文管理。
上面中的fb是文件句柄,通过fb去调用这个问题
何为句柄?
后面学习会遇到文件句柄、窗口句柄,下面是摘取一些网上的见解
句柄可以理解为就是一个id或者编码,可以凭借这个id对文件或者窗口进行标识了。
举例:就和你去饭店吃饭要排队,前台小姐给你分配了一个编号一样,然后她可以通过编号找到你。

在操作系统或者某种其他编程系统中,句柄就是这样的一个编号,用来对各种奇奇怪怪的东西编号,系统对你来说是一个黑箱,你只能通过这个编号向系统要东西。
句柄就是将直接调用改为间接调用,以避免每次调用的时候在库里搜寻,提高调用速度

2.2 with 上下文管理

with open('test.txt', 'r', encoding='utf-8') as fb:
    content = fb.read()
    print(content)

with 语句执行完毕会自动关闭文件句柄。

2.3 逐行读取

  • read上面所使用的read会把文本的内容全部返回,很多时候会造成内存一下子变太大,而且有些数据不需要使用的,也会降低效率。下面介绍逐行读取文本内容的方法

在读取文本文件时,经常需要按行读取,文件对象提供了多种方法进行按行读取。

2.3.1readline

从文件中读取一行;如果 f.readline() 返回一个空的字符串,则表示已经到达了文件末尾

with open('test.txt', 'r', encoding='utf-8') as fb:
    print(fb.readline())
    print(fb.readline())
    print(fb.readline())
    print(fb.readline())

2.3.2readlines

以列表的形式返回文件中所有的行。

with open('test.txt', 'r', encoding='utf-8') as fb:
    content = fb.readlines()
    print(content)

2.3.3 迭代(推荐使用此方法)

要从文件中读取行,还可以循环遍历文件对象。这是内存高效,快速的,并简化代码:

with open('test.txt', 'r', encoding='utf-8') as fb:
    for line in fb:
        print(line)

2.4 相对路径与绝对路径

绝对路径

绝对路径是指定了文件在电脑中的具体位置,以 windows 电脑为例:

D:\Pycharm_workspace\day12file\读文本.py

相对路径

相对路径一般是指相对当前脚本的路径,比如上面的案例中的 test.txt 因为和当前脚本在同一个文件夹下,所以可以直接使用 test.txt 作为文件名来操作。
也可显式地表达当前路径 ./test.txt,
./ 表示当前目录
../ 表示上级目录,同理 ../../ 表示上上级目录,依此类推。

使用场景

相对路径:一般情况下项目本身的资源文件和脚本路径相对固定,为了不影响项目的移植性,必须使用相对路径。
相对路径:需要读取操作系统中固定位置的系统文件一般使用绝对路径。

3.读二进制文件

任何文件都可以以二进制读的方式打开,读取 test.txt 的二进制内容。
** 读取二进制文件时(也就是mode=rb时),不需要encoding参数**

# mode=rb,不需要encoding参数
with open('test.txt', 'rb') as fb:
    content = fb.read()
    print(content)
# 也可以逐行读取,以\n换行符标志
with open('test.txt', 'rb') as fb:
    for line in fb:
        print(line)

4. 写文本文件

4.1 清除写 w

mode=w 没有文件就创建,有就清除内容,小心使用

with open('test.txt', 'w', encoding='utf-8') as fb:
    fb.write('锄禾\n')
    fb.write('锄禾日当午,汗滴禾下土;\n')
    fb.write('谁知盘中餐,粒粒皆辛苦。\n')

4.2 追加写 a

mode=a 追加到文件的最后

# mode=a 追加到文件的最后
with open('test.txt', 'a', encoding='utf-8') as fb:
    fb.write('静夜思\n床前明月光,疑是地上霜;\n举头望明月,低头思故乡。\n')

4.3 排他写 x

在当前目录中创建文件 test.txt,存在则不创建,且会报错

with open('test2.txt', 'x', encoding='utf-8') as fb:
    fb.write('1天空之城1')

FileExistsError: [Errno 17] File exists: 'test2.txt'

5.写二进制文件

在写模式后加 b 即是写二进制模式,这种模式下写入内容为字节数据。

例如:将爬到的图片二进制信息写入文件中。

import requests

url = 'https://pic.netbian.com/uploads/allimg/211115/232008-1636989608f1ca.jpg'
response = requests.get(url)
# print(response.content) # 打印出图片的二进制信息
with open('美女壁纸.jpg', 'wb') as f:
    f.write(response.content)

6.读写文件

有时候需要能够同时读写文件,在模式后面加上 + 号即可给读模式添加写,给写模式添加读

7.案例:python 处理解析 CSV 文件

读取csv文件并解析为嵌套列表
方法一:
实现思路:用readlines把列表的形式返回文件中所有的行,但是此时各个元素的末端有回车,利用for循环获取到每个元素,strip()把回车符去掉,再把每个元素(字符串)转换成列表

with open('鸢尾.csv', 'r', encoding='gbk') as fb:
    content = fb.readlines()

    for i in range(len(content)):
        content[i] = content[i].strip()
        content[i] = content[i].split(',')

方法二(推荐):

data = []
with open('鸢尾.csv', 'r', encoding='gbk') as fb:

    for line in fb:
        # 去掉每行末端的回车
        line = line.strip()
        data.append(line.split(','))
    print(data)

# 将数据写为csv文件
with open('test.csv', 'w', encoding='utf-8') as f:
    for item in data:
        f.write(','.join(item) + '\n')

8.文件指针

open 函数返回的文件对象使用文件指针来记录当前在文件中的位置。

8.1 read 方法

在读模式下,使用文件对象的 read 方法可以读取文件的内容。它接收一个整数参数表示读取内容的大小,文本模式下表示字符数量,二进制模式下表示字节大小。

# 读取前面三个字节 '锄禾\n'
with open('test.txt', 'r', encoding='utf-8') as f:
    content = f.read(3)
    print(content)
with open('test.txt', 'rb') as f:
    content = f.read(3)
    print(content) #输出前面三个字节:b'\xe9\x94\x84',实际上就是一个锄字

'锄'.encode('utf-8') # 三个字节b'\xe9\x94\x84'
当以读的方式打开文件后文件指针指向文件开头,执行 read 操作之后,根据读取的数据大小指针移动到对应的位置。

8.2 tell 方法

文件对象的 tell 方法返回整数,表示文件指针距离文件开头的字节数。

with open('test.txt', 'r', encoding='utf-8') as f:
    print(f.tell())
    content = f.read(3)
    print(content)
    print(f.tell())

r 模式打开文件后文件指针指向文件开头,执行 read 操作之后,根据读取的数据大小指针移动到对应的位置。

with open('test.txt', 'a', encoding='utf-8') as f:
    print(f.tell())
243

a 模式打开文件后文件指针指向文件末尾。

8.3 seek 方法

通过文件对象的 seek 方法可以移动文件句柄

seek 方法接收两个参数:

  • offset 表示偏移指针的字节数
  • whence 表示偏移参考,默认为 0
    0 表示偏移参考文件的开头,offset 必须是 >=0 的整数
    1 表示偏移参考当前位置,offset 可以是负数
    2 表示偏移参考文件的结尾,offset 一般是负数
    注意文本模式下只允许从文件的开头进行偏移,也即只支持 whence=0
with open('test.txt', 'r', encoding='utf-8') as f:
    print(f.read(3))
    # 跳转到文件开头
    f.seek(0)
    # 再读取第一个字
    print(f.read(1))

锄禾

with open('test.txt', 'rb') as f:
    # 读取文件最后的10字节
    f.seek(-10,2)
    print(f.read())
b'\xe5\x8f\x88\xe7\x94\x9f\xef\xbc\x81\n'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容