- Python程序设计--文件 *** 作和文本编码
- 1 .文件 *** 作
- *** 作文件的函数/方法
- read 方法 -- 读取文件
- 文件指针
- 打开文件的方式
- 按行读取文件内容
- 文件读写案例 —— 复制文件
- 文件/目录的常用管理 *** 作
- 2.文本编码
- 文本文件的编码格式
- ASCII 编码和 UNICODE编码
- ASCII 编码
- UTF-8 编码格式
- Unicode 字符串
- 练习
- 3.正则表达式
(1)文件的概念
- 计算机的 文件 ,就是存储在某种 长期储存设备 上的一段 数据
- 长期存储设备包括:硬盘、U盘、移动硬盘、光盘。
(2)文件的作用
- 将数据长期保存下来,在需要的时候使用
(3)文件的存储方式 - 在计算机中,文件是以 二进制 的方式保存在磁盘上的
(4)文本文件和二进制文件
- 文本文件
- 可以使用 文本编辑软件 查看
- 本质上还是二进制文件 例如:python 的源程序
- 二进制文件
- 保存的内容 不是给人直接阅读的,而是 提供给其他软件使用的
- 例如:图片文件、音频文件、视频文件等
- 二进制文件不能使用文本编辑软件 查看
(5)文件的基本 *** 作
*** 作文件的套路
在 计算机 中要 *** 作文件的套路非常固定,一共包含三个步骤:
- 打开文件–>将硬盘中的数据 调到内存
- 读、写文件 -->都在内存中进行,写文件 最终会将内存中的数据,写入到硬盘
- 读 将文件内容读入内存
- 写 将内存内容写入文件
- 关闭文件
在 python 中要 *** 作文件,需要记住 一个函数 和 三个方法
open 函数负责打开文件,并且返回文件对象
read/write/close 三个方法都需要通过 文件对象 来调用
- open 函数的第一个参数是要打开的文件名(文件名区分大小写)
- 如果文件 存在,返回 文件 *** 作对象
- 如果文件 不存在,会 抛出异常
- read 方法可以一次性 读入 并 返回 文件的 所有内容
- close 方法负责 关闭文件
- 如果忘记关闭文件,会造成系统资源消耗,并且会影响到后续对文件的访问
- 注意: 方法执行后,会把 文件指针 移动到 文件的末尾
# 1.打开文件
file = open("README",encoding='UTF-8') # 文件名区分大小写
# 2.读取文件内容
text = file.read()
print(text)
# 3.关闭文件
file.close()
提示:在开发中,通常会先编写 打开 和 关闭 的代码,再编写中间针对文件的 读/写 *** 作!
文件指针- 文件指针 标记 从哪个位置开始读取数据
- 第一次打开 文件时,通常 文件指针会指向文件的开始位置
- 当执行了 read 方法后,文件指针会移动到 读取内容的末尾 默认情况下会移动到 文件末尾
# 1.打开文件
file = open("README",encoding='UTF-8') # 文件名区分大小写
# 2.读取文件内容
text = file.read()
print(text)
print("-"*50)
text = file.read() #重新读取文件查看结果
print(text)
# 3.关闭文件
file.close()
打开文件的方式
- open 函数默认以 只读方式 打开文件,并且返回文件对象
语法如下:
f = opne(文件名,访问方式)
提示:频繁的移动文件指针,会影响文件的读写效率,开发中更多的时候会以 只读、只写 的方式来 *** 作文件
- open 函数默认以 只读方式 打开文件,所以文件不能被写入
- 使用 只写 参数
- 使用 追加 参数 a
- read 方法默认会把文件的 所有内容 一次性读取到内存
- 如果文件太大,对内存的占用会非常严重
readline 方法
- readline 方法可以一次读取一行内容
- 方法执行后,会把 文件指针 移动到下一行,准备再次读取
读取大文件的正确姿势
# 如果文件太大,在读取文件的时候,如果把内容全部读取,会占用比较大的内存空间
# 可以采用一行一行读取的形式
with open("README", 'r', encoding='utf-8') as recv:
while True:
print(recv.readline().strip("\n")) # .strip() 方法,会将读取到的文本末端的 \n \t 空格等去掉
if not recv.readline():
break
文件读写案例 —— 复制文件
"""
目标
用代码的方式,来实现文件复制过程
小文件复制
打开一个已有文件,读取完整内容,并写入到另一个文件
"""
recv = open("README", 'r', encoding='utf-8') # 返回一个对象,也叫一个句柄
打开README 文件,用 只读的形式打开 ,文本编码格式是 UTF-8
# 对句柄进行 *** 作
print(recv.read())
# 完成 *** 作之后,要关闭文件 句柄,从内存中将句柄删除
recv.close()
"""
# r w a r+ w+ a+
# r 只读
# w 只写 不能读
# a 追加 不能读
# r+ 读写 写的 *** 作,不覆盖源文本。
# w+ 读写, 最开始 *** 作的时候,会将文件覆盖,然后才能进行 读或写的 *** 作.
# 如果 在'w+模式下,进行read() *** 作,则返回 字符串的长度'
# a+ 读写, 指针放在文件末尾 执行 write() *** 作, 会在文本末尾,继续写, 读取不到内容
with open("README", 'r', encoding='utf-8') as recv:
print(recv.read())
"""
'''
大文件复制
打开一个已有文件,逐行读取内容,并顺序写入到另一个文件
'''
# 复制文件的本质,是 先读取一个文件,然后将内容写入第二个文件
# 有几个 open ? 2个, 首先 open第一个文件,都内容, 再打开第二个文件,再写内容, 最后关闭两个文件
# 方法1
recv = open("README",'r',encoding='utf-8')
content = recv.read()
print(content)
recv2 = open("README_副本",'w',encoding='utf-8')
recv2.write(content)
recv2.close()
recv.close()
# 方法二:
with open('README', 'r', encoding='utf-8') as recv:
content = recv.read()
with open('README_副本', 'w', encoding='utf-8') as recv2:
recv2.write(content)
print("程序执行结束")
#大文件复制
with open('README', 'r', encoding='utf-8') as recv:
with open('README_copy', 'w', encoding='utf-8') as recv2:
while True:
content = recv.readline()
if not content:
break
recv2.write(content)
文件/目录的常用管理 *** 作
- 在 终端/文件浏览器 中可以执行常规的 文件/目录 管理 *** 作,
- 例如: 创建、重命名、删除、改变路径、查看目录内容……
- 在 Python中,如果希望通过程序实现上述功能,需要导入 os 模块
文件 *** 作
# 使用到的模块 os 模块
"""
rename
remove
"""
import os
# os.rename('README_copy', 'README_copy_reanme')
# os.remove('README_copy_reanme')
# getcwd
print(os.getcwd()) # 获取当前文件所在的绝对路径, 返回路径名 ==》 C:\Users\karl_\Desktop22042
# listdir # 列举 目录中的文件或目录
print(os.listdir(r'/'))
# mkdir
# os.mkdir('dir1') # 相对路径
os.mkdir(r'C:\Users\karl_\Desktop22042\dir2') # 绝对路径
# chdir
os.chdir('dir1')
目录 *** 作
import os
path_1 = "tmp"
# 查看当前工作目录
retval = os.getcwd()
print("当前工作目录为 %s" % retval)
# 修改当前工作目录
os.chdir(path_1)
# 查看修改后的工作目录
retval = os.getcwd()
print("目录修改成功 %s" % retval)
print(os.path.isdir(retval))
2.文本编码
文本文件的编码格式
- 文本文件存储的内容是基于 字符编码 的文件,常见的编码有 ASCII 编码,UNICODE 编码等
- Python 2.x 默认使用 ASCII 编码
- Python 3.x 默认使用UTF-8 编码
计算机中只有 256 个 ASCII 字节
一个 ASCII 在内存中占用 1个字节 的空间
8个 0/1 的排列组合方式一共有 256 种,也就是 2**8 种
- 计算机中使用1-6个字节 来表示 一个 utf-8 字符,涵盖了 地球上几乎所有地区的文字
- 大多数汉字会使用 3个字节 表示
- UTF-8是 Unicode 编码的一种编码格式
Python 2.x 中如何使用中文
在 Python 2.x 文件的第一行 增加以下代码,解释器 会以 utf-8 编码来处理 python 文件
# *-* coding:utf-8 *-*
也可以使用
# coding=utf-8
Unicode 字符串
- 在 Python 2.x 中,即使指定了文件使用 UTF-8 的编码格式,但是在遍历字符串时,依然会 以字节为单位遍历 字符串
- 要能够 正确的遍历字符串,在定义字符串时,需要 在字符串的引号前,增加要给 小写字母 u,告诉解释器这是一个 Unicode 字符串(使用utf-8 编码格式的字符串)
#poem.txt
我绝不承认两颗真心的结合,
会有任何障碍;爱算不得真爱,
若是一看见人家改变便转舵,
或者一看见人家转弯便离开。
哦,绝不!爱是亘古长明的灯塔,
它定睛望着风暴却兀不为动;
爱又是指引迷舟的一颗恒星,
你可量它多高,它所值却无穷。
爱不受时光的播弄,尽管红颜
和皓齿难免遭受时光的毒手;
爱并不因瞬息的改变而改变,
它巍然矗立直到末日的尽头。
我这话若说错,并被证明不确,
就算我没写诗,也没人真爱过。
"""
需求 给诗 加上行号
思路: 读取诗的每一行,在每一行前面+行号, 将新的 文件储存下来
不要在源文件上改--- 保留好源文件
"""
# 读取诗
with open('pome.txt', 'r', encoding='utf-8') as file_obj:
# i = 0
# content = file_obj.readlines()
# while i <= 100:
# if not file_obj.readline():
# break
# print(f"{i}." + content[i+1]) # ---》 写入新的文件
# # 写入新文件
# with open("new_pome.txt", 'a', encoding='utf-8') as new_file:
# new_file.write(f"{i}." + content[i+1])
#
# i += 1
contents = file_obj.readlines()
with open("new_pome.txt", 'a', encoding='utf-8') as new_file:
for i in range(len(contents)):
# print(str(i)+'.'+ contents[i])
new_file.write(str(i + 1) + '.' + contents[i])
"""
根据链接 ,下载图片
用python 模拟 浏览器 通过链接, 从 web 服务器 下载内容
"""
"""
http://www.kaotop.com/file/tupian/20220425/wallhaven-l3p9er.png
"""
import requests
# 写一个 get的 请求报文
url = "http://www.kaotop.com/file/tupian/20220425/wallhaven-o3gqm5.jpg"
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"}
# http://www.useragentstring.com/
res = requests.get(url, headers)
# print(res) #
# print(res.content) # res.content 就是 获取到的内容 二进制内容
# 将获取到的内容写入硬盘
with open("pic/2.png", mode='wb') as file_obj:
file_obj.write(res.content)
"""
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44
"""
以下是stock.csv文件
"""
筛选内容
筛选当前价 大于20的所有股票数据
"""
with open('files/stock.csv', 'r', encoding='utf-8') as file:
file.readline() # 让指针到达第二行
for line in file:
# print(line.splitlines()) # 将 file (从源文件的 第二行开始,)的每一行,都生成一个列表
price = float(line.split(',')[2])
# 如果价格 大于 20,把他们筛选出来
if price > 20:
print(line)
"""
下载网页图片
"""
import requests
import os
headers = {
"User-Agent": "User-Agent:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;"}
with open('./files/mv1.csv', 'r', encoding='utf-8') as file_object:
file_object.readline() # 读取第一行,让指针从第二行开始
for line in file_object:
print(line.split(",")) # 24501619,小忆控,http://www.kaotop.com/file/tupian/20220425/x86eko.jpg
# user_id = line.split(",")[0]
# user_name = line.split(",")[1]
# url = line.split(",")[2].strip()
# print(url)
# res = requests.get(url, headers)
# print(res)
# 判断文件夹是否存在,如果不存在,创建一个新的文件夹
# if not os.path.exists('download'):
# os.mkdir('download')
# with open('download/{}.jpg'.format(user_name), mode='wb') as png_object:
# png_object.write(res.content)
3.正则表达式
- 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配
- Python 自1.5版本起增加了re 模块,它提供Perl 风格的正则表达式模式。
- re 模块使 Python 语言拥有全部的正则表达式功能。
- compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
- re模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
# 正则表达式 re
# 处理字符串
"""
方法:
match 匹配 要从 字符串 开头去匹配,如果不匹配,返回None
search 查找字符串,如果有符合条件的 子字符串 ,返回结果,返回字符串的位置
findall 匹配整个字符串,一直找到字符串结尾,返回结果,没有返回子字符串的位置
sub
"""
import re
# 处理字符串
msg = "娜扎热巴佟丽娅热巴"
# 查看能不能匹配 娜扎
# pattern = re.compile("娜扎")
# result = re.compile("娜扎").match(msg)
result1 = re.match("热巴", msg)
result2 = re.search("热巴", msg)
result3 = re.findall("热巴", msg)
print(result1)
print(result2)
print(result3)
import re
r"""
[]表示一个字符位
------次数
# 定义正则验证次数: *+?
# "*" 用于将前面的模式匹配0次或多次(贪婪模式,尽可能多的匹配) >=0
# "+" 用于将前面的模式匹配1次或多次(贪婪模式) >= 1
# "?" 用于将前面的模式匹配0次或1次(贪婪模式)
# "*?, +?, ??" 及上面三种特殊字符的非贪婪模式(尽可能少的匹配)
# "{m}" 用于验证将前面的模式匹配m次
# "{m,}" 用于验证将前面的模式匹配 m次或者多次 >= m
# "{m,n}" 用于将前面的模式匹配 m次到 n次(贪婪模式),即最小匹配 m次,最大匹配 n次。 大于等于m,小于等于n
# "{m,n}?" 即上面 "{m,n}" 的非贪婪版本
------- 开头结尾
$ 用于匹配字符串的末尾,(如果末尾有换行符 \n,就匹配\n前面的字符),即行尾
^ 用于匹配字符串的开头,match 自动使用这种方法
"."用于匹配除换行符(\n)之外的所有字符
------- 预定义字符
# \A: 表示从字符串的开始出匹配
# \Z: 表示从字符串的借书处匹配,如果存在换行,只匹配到换行前的结束字符串
# \b: 匹配一个单词边界,也就是指单词和空格间的位置。 例如"py\b"可以匹配"python"中的"py",但不能匹配
# "openpyxl"中的"py"
# \B: 匹配非单词边界。 "py\b" 可以匹配 "openpyxl" 中的"py",但是不能匹配"python 中的 py"
# \d: 匹配任意数字,等价于[0-9] todo digit
# \D: 匹配任意非数字字符,等价于[^\d] TODO ^写在[]表示 非 大写表示非
# \s: 匹配任意空白字符,等价于[\t\n\r\f] space
# \S: 匹配任意非空白字符,等价于[^\s]
# \w: 匹配任意字符数字及下划线,等价于[^\w]
# \\: 匹配原意的反斜杠 \
"""
msg2 = "l1askdjfl2jsaljflaa3sdf6l" # 字母+数字+字母
result = re.search("[a-z][0-9][a-z]", msg2)
result2 = re.findall("[a-z][0-9][a-z]", msg2)
print(result)
print(result2)
msg3 = "L1askdjfl22JsaljflaA3sdf6l" # 字母(大小写)+数字(可以有多个)+字母
result3 = re.findall("[a-zA-Z][0-9][a-zA-Z]", msg2)
print(result3)
# 验证一个 QQ号 全是数字 不能以 0 开头 5-11位
qq = "12632189711"
result4 = re.match("[1-9][0-9]{4,10}$", qq)
print(result4)
# 用户名: 要求 用户名可以是 字母或则数字,不能以数字开头,用户名长度必须6位以上
username = "admin_00111111" # ^ $ 匹配规则,从头到尾,都要匹配上
result5 = re.search(r"^[a-zA-Z][\w]{5,}$", username)
print(result5)
# \b boundary
# 检索出 所有的 .py 文件名
msg = "aa.py a*.py ab.txt bb.py cc.png dd**.py abyb.txt"
result6 = re.findall(r"[\w]+[*]*\.py\b", msg)
print(result6)
# 手机号码
# 规则 第一位 1 第二位 356789 第三位
phone_number = "13122223333"
result7 = re.match("^[1][356789][\d]{9}$", phone_number)
print(result7)
import re
# 匹配数字 0 到 100
# 5 50 100 03
# 第一位不能是0,第二位 0-9 只有100 才会有第三位, 如果取值位 0, 也符合
num = "100"
result = re.match("[1-9]?[0-9]?$|100$", num) # "?" 用于将前面的模式匹配0次或1次 # [1-9]?[0-9]?$ 只能匹配0-99
print(result)
# 验证邮箱 @qq.com @163.com @126.com .cn .net
# @前面的字符 5-20位
email = "karl_go@yeah.net"
resutlt1 = re.match(r"\w{5,20}@(qq|163|126|yeah)\.(com|net|cn)$", email)
print(resutlt1)
# 电话号码 带区号, 分别提取 区号和电话号码 -----》 分组
# 400-1895555 022-60737112
phone = "400-1895555"
result2 = re.match(r"(\d{3,4})-(\d{7,8}$)", phone)
print(result2)
print(result2.group(1)) # 第一组的内容
print(result2.group(2)) # 第二组的内容
print(result2.groups()) # 每个组 都提取出来,生成一个元组
# 提取标签里面的内容
html = 'a@c'
result3 = re.match(r'<[\w]+>(.+)[\w]+>', html)
print(result3.group(1))
# 提取标签和里面的内容
html = 'a@c'
result4 = re.match(r'<([\w]+)>(.+)>', html)
print(result4.group(1))
print(result4.group(2))
# 多个标签
html = "hello"
result5 = re.match(r'<(\w+)><(\w+)>(.+)>>', html)
print(result5.groups())
print(result5.group(1), result5.group(2), result5.group(3)) # html h1 hello
html2 = "hello"
result6 = re.match('<(?P\w+)><(?P\w+)>(.+)(?P=n2)>(?P=n1)>' ,html2)
print(result6.groups())
# sub 替换, 将符合规则的字符串 替换成 指定字符串
import re
msg = "java:99,python:0,C:59"
result = re.sub(r"\d+", "90", msg)
print(result)
# split 切割 如果遇到符合规则的字符串,进行切割,将结果保存到列表
msg1 = "java:99,python:0,C:59"
result = re.split(r"[:,]", msg1)
print(result)
# 贪婪和非贪婪
import re
msg = 'abc12333333333333333abc'
result = re.match(r'abc\d{4,8}?', msg) # "+" 用于将前面的模式匹配1次或多次(贪婪模式) >= 1
print(result)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)