python自动化测试

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

2021-11-15  本文已影响0人  失忆的蝴蝶

一、文件概述

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

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. 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 逐行读取

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

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 方法接收两个参数:

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'
上一篇下一篇

猜你喜欢

热点阅读