百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python文件操作的实用编程技巧总结,建议收藏学习

off999 2024-09-27 13:57 34 浏览 0 评论

这个问题看似简单,但是由于py2 和 py3 的巨大差异导致我们依然要深入研究一下。

那么 python2 和 python3 的什么区别导致了这种差异的发生呢?

有需要Python学习资料的小伙伴吗?小编整理【一套Python资料、源码和PDF】,感兴趣者可以关注小编后私信学习资料(是关注后私信哦)反正闲着也是闲着呢,不如学点东西啦

答:python2 和 python3 之间字符串的语意发生了变化

python2 有两种字符串的类型:

(1)str

表面上看是字符串,但是实际上是抽象的一串连续的字节(字符串中每个字符都是一个字节)

(2)unicode

这个类型是在更多不同的语言加入以后不得不进行调整的,不再用一个字节表示一个字符,但是,我们进行文件操作的时候是不支持直接将多个字节一下子存储进去的,我们必须将其转化成某种单个字节的编码再进行存储操作

示例代码:

将文字编码:

Bash
In [1]: a = u'你好世界'
In [2]: a.encode('utf8')
Out[2]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'
In [3]: a.encode('gbk')
Out[3]: '\xc4\xe3\xba\xc3\xca\xc0\xbd\xe7'

可以看到 utf-8 使用的字节比Gbk多

将文字解码:

注意:这里编码和解码一定要对应,否则会出现乱码。

代码示例:

Bash
In [5]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'.decode('gbk')
Out[5]: u'\u6d63\u72b2\u30bd\u6d93\u682b\u666b'
In [6]: print u'\u6d63\u72b2\u30bd\u6d93\u682b\u666b'
浣犲ソ涓栫晫

代码示例:

Bash
In [8]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'.decode('utf8')
Out[8]: u'\u4f60\u597d\u4e16\u754c'
In [9]: print u'\u4f60\u597d\u4e16\u754c'
你好世界

1.python2 的文本读写

文本就是Unicode 字符串,我们写入文件前先要对其选择一个方式进行编码,我们读取文件的时候也要对其进行先解码,将其换原成 unicode 。

文本的写入:

Bash
f = open('test.txt','w')
s = u'你好世界'
f.write(s.encode('utf8'))

文本的读出:

Bash
In [8]: f = open('test.txt','r')
In [9]: t = f.read()
In [10]: t
Out[10]: '\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xb8\x96\xe7\x95\x8c'

可以看到这样读出来的都是字节码

我们必须要进行转化:

Bash
In [11]: t.decode('utf8')
Out[11]: u'\u4f60\u597d\u4e16\u754c'
In [12]: print u'\u4f60\u597d\u4e16\u754c'
你好世界

2.python3 的文本读写

python3 对字符串的支持更加清晰合理,unicode 就是 python3 中的 str 而 str 就是python3 中的 byte

就比如说,python2 中字符串前面加一个u 才代表 unicode 字符串但是 python3 什么都不用加直接就是,反倒是如果想成为一个 byte 字符串要加 b

python3 的读写可以指定一个参数 encoding = ‘’ 自动的进行编解码

文本的写入:

Bash
f = open('test.txt','w',encoding = 'utf8')
f.write("国庆快乐")

文本的读出:

Bash
f = open('test.txt','r',encoding='utf8')
t = f.read()
print (t)

二、如何处理二进制文件

wav 是音频问价,前44字节是文件的头信息,我们可以尝试将其读出来

Bash
In [6]: f = open('test.wav','rb')
In [7]: info = f.read(44)
In [8]: info
Out[8]: 'RIFFt\x9b\x0b\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00\x11+\x00\x00D\xac\x00\x00\x04\x00\x10\x00dataP\x9b\x0b\x00'

那么我们如何将其解析出来呢?

我们可以使用 struct 这个库中的unpack 方法

举个例子:

h 是一个 short 的意思

Bash
import struct
print struct.unpack('h','\x01\x02')//小端序
print '\n'
print struct.unpack('>h','\x01\x02')//大端序
(513,)//--------->2x256+1
(258,)//--------->1x256+2

比如我们的音频文件的 22-24 字节是声道数,于是我们就能使用这个函数将其解析出来

代码示例:

Bash
import struct
f = open('test.wav','rb')
info = f.read(44)
print struct.unpack('h',info[22:24])

结果:

Bash
(2,)

说明这个音频文件是双声道

再比如我们想读音频文件的采样频率,这个东西是24-28 4个字节

代码示例:

Bash
import struct
f = open('test.wav','rb')
info = f.read(44)
print struct.unpack('i',info[24:28])//因为这里是4个字节所以我们就是用的i

结果:

Bash
(11025,)

综合实验:

我们现在想读入音频文件的数据部分,并且不能以字符串的形式,因为字符串的形式没法进行输入操作,我们可以将其以每两个字节为一组读入一个buf

我们首先看一下我们的音频的数据有多大:

Bash
import array
f = open('test.wav', 'rb')
f.seek(0, 2) # 移动指针的位置
t = f.tell() # 返回指针的位
a = (t-44)/2 # 每两个一组进行分组
print a

a 就是最终的组数

然后我们就创建指定类型大小的Buf,我们把buf初始化,并将44字节以后的输入写入buf

Bash
buf = array.array('h',(0 for _ in xrange(a)))
f.seek(44)
f.readinto(buf)

接下来我们对 buf 进行操作,将操作完的结果重新写成另一个文件

info = f.read(44)

for i in xrange(a):

buf[i]/=8

Bash
f2 = open('demo.wav','wb')
f2.write(info)
buf.tofile(f2)
f2.close()

以上步骤,我们其实已经将我们的音频声音变成了原来的1/8

代码示例:

Bash
# coding=utf-8
import struct
import array
f = open('test.wav', 'rb')
info = f.read(44)
f.seek(0, 2) # 移动指针的位置
t = f.tell() # 返回指针的位置
a = (t-44)/2
buf = array.array('h',(0 for _ in xrange(a)))
f.seek(44)
f.readinto(buf)
for i in xrange(a):
 buf[i]/=8
f2 = open('demo.wav','wb')
f2.write(info)
buf.tofile(f2)
f2.close()

三、如何设置文件的缓冲

将文件写入硬件设备的时候是按照块进行写入的,每个块有固定的大小,也就是说,进行一次写入操作的时间是固定的,不管你有没有把块填满,因此如果没有缓冲,就会在块不满的情况下进行写入,导致次数过多时间过长,于是我们需要设置文件缓冲。

缓冲又分为全缓冲和行缓冲,一般文件的缓冲就是全缓冲,意思就是填满一个就释放一个,而行缓冲就是遇到换行符就释放。

当然并不是所有的设备都需要缓冲的,串口设备我们就希望能即时发送,于是我们不设置缓冲区

1.检验缓冲区大小实验:

ipython :

In [13]: f = open(‘demo.txt’,’w’)

In [14]: f.write(‘abc’)

In [15]: f.write(‘+’*4093)

In [16]: f.write(‘-‘)

另一个终端:

Bash
$ tail -f demo.txt

14、15 命令执行以后 tail 都没反应,直到16命令执行,在tail 后面输出了 abc和 4093个*,可见缓冲区的大小是4096字节

2.修改默认缓冲区的大小

(1)全缓冲:

open 函数 有一个 buffering 的选项可以设置缓冲区大小,我们设置为大于一的整数

Bash
f = open('demo.txt','w',buffering = 2048)

(2)行缓冲:

将 buffering 设置为1

Bash
f = open('demo.txt','w',buffering = 1)

(3)无缓冲:

将 buffering 设置为0

Bash
f = open('demo.txt','w',buffering = 0)

四、如何将文件映射到内存

需求:

1.在访问二进制文件的时候,希望把文件映射到内存空间,实现随机访问

2.嵌入式设备中,寄存器被编址到内存地址空间,我们可以映射 /dev/mem 的某些范围,来操纵这些寄存器

3.如果多个进程映射同一个文件,还能实现进程通信

使用 mmap.mmap()

通过下面这条命令创建一个1M的全0文件:

Bash
dd if=/dev/zero of=demo.bin bs=1024 count=1024

使用 od -x 查看,发现的确是全0

Bash
od -x demo.bin

0000000 0000 0000 0000 0000 0000 0000 0000 0000

*

4000000

我们获取文件描述符

示例代码:

Bash
f = open('demo.bin','r+b')
print f.fileno()

结果:

我们将整个文件映射到变量m

Bash
m = mmap.mmap(num,0,mmap.ACCESS_WRITE) # 这里的0表示的是全部文件

我们看一下内容:

Bash
In [10]: m[100]
Out[10]: '\x00'

修改:

Bash
In [11]: m[100] = '\x08'

查看修改后的内容

Bash
In [12]: m[99:120]
Out[12]: '\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

实际上在这种情况下文件已经被修改。

我们还可以跳过整数倍的页的大小对文件进行修改(页的概念来源于操作系统,如果不了解可以去查一下)

Bash
m = mmap.mmap(num,mmap.PAGESIZE*8,mmap.ACCESS_WRITE,offset = mmap.PAGESIZE*4)

五、如何访问文件的状态

在某些项目中我们需要获取文件的状态,

比如:

(1)文件类型

(2)文件权限

(3)文件最后修改时间

(4)文件的大小

方法一:系统调用

1.os.stat()

2.os.lstat()

它与os.stat 的区别在于它不跟随符号链接文件,意思就是lstat 拿到的是快捷方式的属性,而stat 拿到的是原始文件的属性

3.os.fstat()

这个函数和上面两个函数的区别是这个函数传入的参数是文件描述符,而不是上面两个参数传入的路径。

示例代码:

Bash
In [3]: import os
In [4]: os.stat('demo.bin')
Out[4]: posix.stat_result(st_mode=33188, st_ino=264254, st_dev=2049, st_nlink=1, st_uid=0, st_gid=0, st_size=1048576, st_atime=1538365252, st_mtime=1538364797, st_ctime=1538364797)

查看文件的类型:

文件的类型就存储在 st_mode 里面,我们需要将其解析

Bash
In [15]: import os
In [16]: s = os.stat('demo.bin')
In [17]: import stat
In [18]: stat.S_ISDIR(s.st_mode)
Out[18]: False

查看文件的权限

Bash
In [19]: s.st_mode & stat.S_IRUSR
Out[19]: 256

只要这个返回值大于0就说明有用户读的权限

Bash
In [20]: s.st_mode & stat.S_IXUSR
Out[20]: 0

可见用户的执行权限是0

查看文件的最后访问时间:

Bash
In [25]: import time
In [26]: time.localtime(s.st_atime)
Out[26]: time.struct_time(tm_year=2018, tm_mon=10, tm_mday=1, tm_hour=11, tm_min=40, tm_sec=52, tm_wday=0, tm_yday=274, tm_isdst=0)

方法二:快捷函数

快捷函数在底层实现上是利用的是系统函数,但是会让你操作起来更加方便

判断文件类型:

Bash
In [27]: os.path.isdir('demo.bin')
Out[27]: False
In [28]: os.path.isfile('demo.bin')
Out[28]: True

判断文件最后访问时间:

Bash
In [32]: time.localtime(os.path.getatime('demo.bin'))
Out[32]: time.struct_time(tm_year=2018, tm_mon=10, tm_mday=1, tm_hour=11, tm_min=40, tm_sec=52, tm_wday=0, tm_yday=274, tm_isdst=0)

六、如何使用临时文件:

比如我们采集数据进行分析,但是我们只需要保存结果,我们采集的数据如果常驻内存就会让电脑崩溃,于是我们将这个数据放在临时文件中(外部存储),在文件关闭后将被删除

示例代码:

Bash
In [15]: from tempfile import TemporaryFile,NamedTemporaryFile
In [16]: f = TemporaryFile()
In [17]: f.write('abc'*10000)
In [18]: f.seek(0)
In [19]: f.read(100)
Out[19]: 'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabca'

这个临时文件在系统中是找不到的,如果我们想创建一个能在文件系统中看到的临时文件,我们就用NamedTemporaryFile

示例代码:

我们能看到文件路径

Bash
In [20]: nte = NamedTemporaryFile()
In [21]: nte.name
Out[21]: 'c:\\users\\k0rz3n\\appdata\\local\\temp\\tmpob51yb'

如果我们重新创建一个文件的话,原来的文件就会被关闭,关闭以后临时文件就会被自动删除,如果我们不想让他删除,我们在创建的时候就要设置一个参数

Bash
nte = NamedTemporaryFile(delete = False)

有需要Python学习资料的小伙伴吗?小编整理【一套Python资料、源码和PDF】,感兴趣者可以关注小编后私信学习资料(是关注后私信哦)反正闲着也是闲着呢,不如学点东西啦

相关推荐

python入门到脱坑经典案例—清空列表

在Python中,清空列表是一个基础但重要的操作。clear()方法是最直接的方式,但还有其他方法也可以实现相同效果。以下是详细说明:1.使用clear()方法(Python3.3+推荐)...

python中元组,列表,字典,集合删除项目方式的归纳

九三,君子终日乾乾,夕惕若,厉无咎。在使用python过程中会经常遇到这四种集合数据类型,今天就对这四种集合数据类型中删除项目的操作做个总结性的归纳。列表(List)是一种有序和可更改的集合。允许重复...

Linux 下海量文件删除方法效率对比,最慢的竟然是 rm

Linux下海量文件删除方法效率对比,本次参赛选手一共6位,分别是:rm、find、findwithdelete、rsync、Python、Perl.首先建立50万个文件$testfor...

数据结构与算法——链式存储(链表)的插入及删除,

持续分享嵌入式技术,操作系统,算法,c语言/python等,欢迎小友关注支持上篇文章我们讲述了链表的基本概念及一些查找遍历的方法,本篇我们主要将一下链表的插入删除操作,以及采用堆栈方式如何创建链表。链...

Python自动化:openpyxl写入数据,插入删除行列等基础操作

importopenpyxlwb=openpyxl.load_workbook("example1.xlsx")sh=wb['Sheet1']写入数据#...

在Linux下软件的安装与卸载(linux里的程序的安装与卸载命令)

通过apt安装/协助软件apt是AdvancedPackagingTool,是Linux下的一款安装包管理工具可以在终端中方便的安装/卸载/更新软件包命令使用格式:安装软件:sudoapt...

Python 批量卸载关联包 pip-autoremove

pip工具在安装扩展包的时候会自动安装依赖的关联包,但是卸载时只删除单个包,无法卸载关联的包。pip-autoremove就是为了解决卸载关联包的问题。安装方法通过下面的命令安装:pipinsta...

用Python在Word文档中插入和删除文本框

在当今自动化办公需求日益增长的背景下,通过编程手段动态管理Word文档中的文本框元素已成为提升工作效率的关键技术路径。文本框作为文档排版中灵活的内容容器,既能承载多模态信息(如文字、图像),又可实现独...

Python 从列表中删除值的多种实用方法详解

#Python从列表中删除值的多种实用方法详解在Python编程中,列表(List)是一种常用的数据结构,具有动态可变的特性。当我们需要从列表中删除元素时,根据不同的场景(如按值删除、按索引删除、...

Python 中的前缀删除操作全指南(python删除前导0)

1.字符串前缀删除1.1使用内置方法Python提供了几种内置方法来处理字符串前缀的删除:#1.使用removeprefix()方法(Python3.9+)text="...

每天学点Python知识:如何删除空白

在Python中,删除空白可以分为几种不同的情况,常见的是针对字符串或列表中空白字符的处理。一、删除字符串中的空白1.删除字符串两端的空白(空格、\t、\n等)使用.strip()方法:s...

Linux系统自带Python2&yum的卸载及重装

写在前面事情的起因是我昨天在测试Linux安装Python3的shell脚本时,需要卸载Python3重新安装一遍。但是通过如下命令卸载python3时,少写了个3,不小心将系统自带的python2也...

如何使用Python将多个excel文件数据快速汇总?

在数据分析和处理的过程中,Excel文件是我们经常会遇到的数据格式之一。本文将通过一个具体的示例,展示如何使用Python和Pandas库来读取、合并和处理多个Excel文件的数据,并最终生成一个包含...

【第三弹】用Python实现Excel的vlookup功能

今天继续用pandas实现Excel的vlookup功能,假设我们的2个表长成这样:我们希望把Sheet2的部门匹在Sheet1的最后一列。话不多说,先上代码:importpandasaspd...

python中pandas读取excel单列及连续多列数据

案例:想获取test.xls中C列、H列以后(当H列后列数未知时)的所有数据。importpandasaspdfile_name=r'D:\test.xls'#表格绝对...

取消回复欢迎 发表评论: