Python文件操作

Python可以高效处理文件,配合正则模块,可以轻松实现提取文本文件关键信息、转换内容格式等功能,现将Python文件操作相关内容以及正则模块使用总结如下。

一、文件的类型与编码

(一) 文件类型

计算机中所有文件都以二进制形式保存在存储介质上,文件类型的区分是逻辑上的区分,是由于文件内容编码逻辑不同导致的,文件可以分为文本文件和二进制文件:

1.文本文件

文本文件是基于字符编码的文件,编码格式包括ASCII、UTF-8等,可以用编辑器直接打开查看,如Python源码、TXT文件。

比如100在ASCII编码的文本文件中会保存为三个字符’1’、‘0’、‘0’,占用三个字节,10000保存为五个字符’1’、‘0’、‘0’、‘0’、‘0’,占用五个字节,每个字符按照编码规则解码就能正常查看文件内容。

2.二进制文件

二进制文件是基于值编码的文件,提供给专用软件使用,根据与专用软件之间的协议规定值的具体含义,不能直接用编辑器打开查看,如图片、音视频文件、Word文档。

比如JPEG文件内容是按照段来存储的,每个段起始两个部分是段的标识: 0xFF+段类型,比如文件头: FFD8,文件尾: FFD9,不同段对应的字节具有不同含义,文件必须通过图片编辑器查看,如果按照文本文件解码就会出现乱码。

(二) 编码方式

编码方式是针对字符而言的,所以只针对文本文件,常用编码方式及区别如下:

  • ASCII:单字节编码,使用7位(128个字符,基础ASCII)或8位(256个字符,扩展ASCII)来表示所有的英文字符、数字、标点符号以及特殊字符
  • GB2312:双字节编码,对文件中任意一个图形字符都采用双字节编码,是最早制定的汉字编码,是ASCII汉字编码的扩充,但是不包含繁体字,兼容ASCII编码
  • Big5:双字节编码,台湾、香港等地区使用的繁体汉字的编码,与GB2312不兼容,兼容ASCII编码
  • GBK:双字节编码,兼容GB2312并在其基础上进行扩展,收录了Big5中所有的繁体字以及更多的汉字字符和符号
  • GB18030:单字节、双字节、四字节分段编码,是GBK的取代版本,在GBK基础上增加了CJK统一汉字扩充A和扩充B的汉字,兼容GBK
  • Unicode:又称为万国码,准确说它是一个字符集,默认以UCS-2标准,用两个字节为每种语言中的每个字符设定了统一并且唯一的编码,具体包括UTF-8、UTF-16、UTF-32三种编码实现方式,这三种编码方式都可以表示目前世界上所有的字符
  • UTF-8:变长编码,以一个字节为基本编码单位,所有字节用一个到四个字节不等,虽然可以表示所有的中文字符,但是**不兼容GBK、GB2312,**空间利用率高,灵活性强,应用广泛,兼容性较好
  • UTF-16:变长编码,以两个字节为基本编码单位,所有字符用两个或者四个字节表示
  • UTF-32:以四个字节为基本编码单位,所有字节都用四个字节表示,空间利用率差
  • ANSI:并不是某一种特定的字符编码,而是在不同的系统中,ANSI表示不同的编码。英文系统中ANSI默认是ASCII编码,简体中文系统中ANSI默认是GB2312编码,繁体中文系统中ANSI默认是Big5编码,不同系统的ANSI编码不兼容

一张图解释,简单明了:
请添加图片描述
注意Python2/3编码兼容性问题:

Python2默认用ASCII编码,Python3默认使用UTF-8编码,如果Python2中使用UTF-8解析文件,则需要在文件的第一行 (在Shebang之后) 添加编码说明,如:

#!/usr/bin/python 
# -*- coding: utf-8 -*-

但是即便添加了coding注释,Python2解释器在读取字符串时仍然是一个一个字节读取,如果要以正确的UTF-8格式读取,则要在字符串前加一个u,这样类似以下代码就不会出错了:

#!/usr/bin/python 
# -*- coding: utf-8 -*-
hello_str = u"Hello世界"

for c in hello_str:
    print(c)

二、文件操作与管理

(一) 文件操作函数/方法

文件的操作主要是打开文件、读写文件、关闭文件,对应一个函数和三个方法:

函数/方法作用返回值
open(name[, mode[, encoding]])函数,用于打开文件,指定的文件名区分大小写,打开模式默认为只读r,编码默认为系统平台编码,如果文件存在则返回文件对象,不存在则抛出异常IO
read([count])将文件内容读取到内存,默认一次性读入并返回文件的所有内容,也可以指定读取count个字节str
readline([count])读取并返回当前文件指针所在行的字符串,读取大文件时常用,可以指定读取count个字节,最多只能读取到单行的字符str
readlines([count])读取并以列表方式返回文件所有的行,可以指定读取count个字节,字节数不足一行的按一行内容返回List(str)
write(str)将指定字符串写入到文件,返回字符串的长度int
writelines(List[str])将指定字符串列表写入到文件None
close()关闭文件,如果忘记关闭文件,会造成系统资源消耗,而且会影响后续对文件的访问None
理解文件指针
  • 文件指针用于标记从哪个位置开始读取数据,第一次打开文件时,文件指针会指向文件的开始位置

  • 文件方法执行后,文件指针会随之变化,比如:执行read方法后,文件指针会移动到文件的末尾,此时如果再执行一次read方法则不会读到任何内容;执行readline方法后,文件指针会移动到下一行的位置,从而可以迭代读取文件内容

(二) 文件打开方式

用open函数打开文件可以有多种操作方法:

file = open(name[, mode[, encoding]])

mode具体打开模式为:

  • r:只读方式打开文件,不存在文件则会抛出异常,函数的缺省设置
  • w:只写方式打开文件,如果存在则会被覆盖,不存在则新建文件
  • a:追加方式打开文件,如果该文件已存在,文件指针会放在文件的结尾,如果不存在,创建新文件写入
  • r+:以读写方式打开文件,文件指针放在文件开头,不存在则抛出异常
  • w+:以读写方式打开文件,如果文件存在则会被覆盖,文件不存在则创建新文件
  • a+:以读写方式打开文件,如果该文件已存在,文件指针会放在文件的结尾,如果不存在,创建新文件写入

encoding可以是ansi、gbk、gb2312等上述所有的编码方式

注意:频繁移动文件指针会影响读写效率,开发中大多时候以只读、只写方式来读取

(三) 文件的管理操作

Python中,如果要实现文件的创建、重命名、删除、改变路径、查看目录内容等,需要导入 os 模块,具体方法如下:

方法作用返回值
os.rename(src_file, dst_file)将src_file文件名重命名为dst_fileNone
os.remove(file)删除file文件None
os.listdir([dir])返回目录列表,默认为当前目录List[str]
os.mkdir(dir[, mode])以mode权限创建路径为dir的目录,mode默认为0777(Windows系统忽略mode值)None
os.rmdir(dir)删除dir指定的空目录,如果目录非空则抛出异常None
os.getcwd()返回当前目录str
os.chdir(dir)改变当前工作目录为dirNone
os.rmdir(dir)删除dir指定的空目录,如果目录非空则抛出异常None
os.path.isdir(dir)判断某dir是否为目录bool
os.path.isfile(file)判断file是否为文件bool

三、正则模块的使用

正则表达式描述了一种字符串匹配的模式,可以用来检查一个字符串是否含有匹配的子串,从而将其替换或者取出符合某个条件的子串等,在文件处理时常会用到。

re 模块使得Python可以通过Perl风格的正则表达式匹配字符串,模块中有两个重要对象,两种对象有不同的方法,注意区分。

(一) 正则 (Pattern) 对象: RegexObject

正则 (Pattern) 对象,由re.compile函数返回的对象,其方法和re模块中的函数相对应,如以下两种方式等同:

# 方法一:
re.match(r"\d*@", "12121212@qq.com")

# 方法二:
pattern = re.compile(r"\d*@")
pattern.match("12121212@qq.com")

将正则表达式编译成正则对象的意义在于,作为对象更加方便调用和修改,正则对象的具体方法如下:

方法作用返回值
match(string[, pos=0[, endpos=len(string)]])string为用于匹配的字符串,pos/endpos为起始位置/结束位置索引,默认从字符串起始位置开始匹配,匹配到则返回匹配对象,不成功返回NoneMatchObject / None
search(string[, pos=0[, endpos=len(string)]])string为用于匹配的字符串,pos/endpos为起始位置/结束位置索引,默认搜索整个字符串并返回第一个成功的匹配对象,不成功返回NoneMatchObject / None
findall(string[, pos=0[, endpos=len(string)]])string为用于匹配的字符串,pos/endpos为起始位置/结束位置索引,默认搜索整个字符串并返回所有成功匹配的子串列表,不成功返回空列表List[str]
split(string[, maxsplit=0])按照匹配的子串将string分割后,并返回子串列表,maxsplit用于指定最大分割次数,不指定默认全部分割List[str]
sub(repl, string[, count=0])字符串string中的匹配项替换成repl,并返回替换后的字符串Str

(二) 匹配 (Match) 对象: MatchObject

匹配 (Match) 对象,由re模块的函数或正则对象的方法如match、search返回的对象,可进一步处理正则匹配到的内容,其方法如下:

方法作用返回值
group([num=0])返回第num个分组匹配的字符串,num默认为0,group() 获得整个匹配的子串str
groups()返回由所有分组匹配的子字符串组成的元祖tuple[str]
start([num=0])返回第num个分组匹配的子串在整个字符串中的起始索引,num默认为0,start() 获得匹配的子串在整个字符串中的起始索引int
end([num=0])返回第num个分组匹配的子串在整个字符串中的末尾索引,num默认为0,end() 获得匹配的子串在整个字符串中的末尾索引int
span([num=0])返回 (start(num), end(num))tuple

(三) Re模块常用函数

函数作用返回值
re.compile(pattern[, flags])编译正则表达式,生成一个正则对象RegexObject
re.match(pattern, string[, flags=0])从字符串的起始位置匹配一个模式,匹配成功返回匹配对象,不成功返回NoneMatchObject / None
re.search(pattern, string[, flags=0])搜索整个字符串并返回第一个成功的匹配对象,不成功返回NoneMatchObject / None
re.findall(pattern, string[, flags=0])搜索整个字符串并返回所有成功匹配的子串列表,不成功返回空列表List[str]
re.split(pattern, string[, maxsplit=0[, flags=0]])按照匹配的子串将string分割后,并返回子串列表,maxsplit用于指定最大分割次数,不指定默认全部分割List[str]
re.sub(pattern, repl, string[, count=0[, flags=0]])将字符串string中的匹配项替换成repl,并返回替换后的字符串Str

上述函数中pattern是匹配的正则表达式,string是要进行匹配的字符串,flags标志位用于控制正则表达式的匹配方式,具体如下:

  • re.I:使得大小写匹配不敏感
  • re.M:使得^$可以匹配到每行的开头和结尾
  • re.S:使 . 可以匹配到包括换行符\n的所有字符
  • re.X:使得正则匹配字符串中tab、换行符以及注释符#后的内容都会被忽略,这样易于正则匹配字符串的组织和解释

通过或符号|来设置多种模式共存,如re.I | re.M

正则表达式规则

1.普通字符(包括字母和数字等)表示他们自身;

2.特殊字符 表示特殊含义,常用特殊字符如下表所示:(如果需要使用特殊字符作为普通匹配字符,则需要\转义)

正则表达式匹配内容
.除了换行符\n以外的所有字符
^字符串的起始位置
$字符串的结束位置
[…]单独标识一组字符,[abc]匹配字符’a’、‘b’和’c’,[a-zA-Z]匹配任何大小写字母
[^…]不在这组字符以外的其他字符
re*匹配0个或多个re表达式,默认贪婪模式
re+匹配1个或多个re表达式,默认贪婪模式
re?匹配0个或1个re表达式,非贪婪方式
re{n}精确匹配n个re表达式
re{n,}匹配n个或多于n个re表达式
re{n,m}匹配n到m个re表达式
re1re2
(re)对正则表达式进行分组,分组可作为一个整体使用,如(abc){1,2}
\1…\9匹配与第1-9个分组相同的内容,如(\d)abc\1,则会匹配1abc1、2abc2等
\w匹配字母数字及下划线,等价于[a-zA-Z0-9_]
\W匹配非字母数字及下划线[^a-zA-Z0-9_]
\d匹配任意数字,等价于[0-9]
\D匹配任意非数字,等价于[^0-9]
\s匹配任意空白字符,等价于[ \f\n\r\t\v]
\S匹配任意非空白字符,等价于[^ \f\n\r\t\v]
\b匹配单词的边界,也就是指单词和空格间的位置,例如 ‘er\b’ 可以匹配 “never” 中的 ‘er’
\B匹配非单词的边界,例如 ‘er\B’ 不可以匹配 “never” 中的 ‘er’,但可以匹配 “perfect” 中的 ‘er’

注意:由于部分正则表达式包含反斜杠 (如: \w\d\s),所以最好使用原始字符串来表示,即在正则表达式前加上rr"\d{1,2}"等价于"\\d{1,2}"

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值