Python文件操作的实用编程技巧总结,建议收藏学习
off999 2024-09-27 13:57 73 浏览 0 评论
这个问题看似简单,但是由于py2 和 py3 的巨大差异导致我们依然要深入研究一下。
那么 python2 和 python3 的什么区别导致了这种差异的发生呢?
有需要Python学习资料的小伙伴吗?小编整理【一套Python资料、源码和PDF】,感兴趣者可以关注小编后私信学习资料(是关注后私信哦)反正闲着也是闲着呢,不如学点东西啦
答:python2 和 python3 之间字符串的语意发生了变化
python2 有两种字符串的类型:
(1)str
表面上看是字符串,但是实际上是抽象的一串连续的字节(字符串中每个字符都是一个字节)
(2)unicode
这个类型是在更多不同的语言加入以后不得不进行调整的,不再用一个字节表示一个字符,但是,我们进行文件操作的时候是不支持直接将多个字节一下子存储进去的,我们必须将其转化成某种单个字节的编码再进行存储操作
示例代码:
将文字编码:
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多
将文字解码:
注意:这里编码和解码一定要对应,否则会出现乱码。
代码示例:
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'
浣犲ソ涓栫晫
代码示例:
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 。
文本的写入:
f = open('test.txt','w')
s = u'你好世界'
f.write(s.encode('utf8'))
文本的读出:
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'
可以看到这样读出来的都是字节码
我们必须要进行转化:
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 = ‘’ 自动的进行编解码
文本的写入:
f = open('test.txt','w',encoding = 'utf8')
f.write("国庆快乐")
文本的读出:
f = open('test.txt','r',encoding='utf8')
t = f.read()
print (t)
二、如何处理二进制文件
wav 是音频问价,前44字节是文件的头信息,我们可以尝试将其读出来
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 的意思
import struct
print struct.unpack('h','\x01\x02')//小端序
print '\n'
print struct.unpack('>h','\x01\x02')//大端序
(513,)//--------->2x256+1
(258,)//--------->1x256+2
比如我们的音频文件的 22-24 字节是声道数,于是我们就能使用这个函数将其解析出来
代码示例:
import struct
f = open('test.wav','rb')
info = f.read(44)
print struct.unpack('h',info[22:24])
结果:
(2,)
说明这个音频文件是双声道
再比如我们想读音频文件的采样频率,这个东西是24-28 4个字节
代码示例:
import struct
f = open('test.wav','rb')
info = f.read(44)
print struct.unpack('i',info[24:28])//因为这里是4个字节所以我们就是用的i
结果:
(11025,)
综合实验:
我们现在想读入音频文件的数据部分,并且不能以字符串的形式,因为字符串的形式没法进行输入操作,我们可以将其以每两个字节为一组读入一个buf
我们首先看一下我们的音频的数据有多大:
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
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
f2 = open('demo.wav','wb')
f2.write(info)
buf.tofile(f2)
f2.close()
以上步骤,我们其实已经将我们的音频声音变成了原来的1/8
代码示例:
# 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(‘-‘)
另一个终端:
$ tail -f demo.txt
14、15 命令执行以后 tail 都没反应,直到16命令执行,在tail 后面输出了 abc和 4093个*,可见缓冲区的大小是4096字节
2.修改默认缓冲区的大小
(1)全缓冲:
open 函数 有一个 buffering 的选项可以设置缓冲区大小,我们设置为大于一的整数
f = open('demo.txt','w',buffering = 2048)
(2)行缓冲:
将 buffering 设置为1
f = open('demo.txt','w',buffering = 1)
(3)无缓冲:
将 buffering 设置为0
f = open('demo.txt','w',buffering = 0)
四、如何将文件映射到内存
需求:
1.在访问二进制文件的时候,希望把文件映射到内存空间,实现随机访问
2.嵌入式设备中,寄存器被编址到内存地址空间,我们可以映射 /dev/mem 的某些范围,来操纵这些寄存器
3.如果多个进程映射同一个文件,还能实现进程通信
使用 mmap.mmap()
通过下面这条命令创建一个1M的全0文件:
dd if=/dev/zero of=demo.bin bs=1024 count=1024
使用 od -x 查看,发现的确是全0
od -x demo.bin
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
4000000
我们获取文件描述符
示例代码:
f = open('demo.bin','r+b')
print f.fileno()
结果:
我们将整个文件映射到变量m
m = mmap.mmap(num,0,mmap.ACCESS_WRITE) # 这里的0表示的是全部文件
我们看一下内容:
In [10]: m[100] Out[10]: '\x00'
修改:
In [11]: m[100] = '\x08'
查看修改后的内容
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'
实际上在这种情况下文件已经被修改。
我们还可以跳过整数倍的页的大小对文件进行修改(页的概念来源于操作系统,如果不了解可以去查一下)
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()
这个函数和上面两个函数的区别是这个函数传入的参数是文件描述符,而不是上面两个参数传入的路径。
示例代码:
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 里面,我们需要将其解析
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
查看文件的权限
In [19]: s.st_mode & stat.S_IRUSR Out[19]: 256
只要这个返回值大于0就说明有用户读的权限
In [20]: s.st_mode & stat.S_IXUSR Out[20]: 0
可见用户的执行权限是0
查看文件的最后访问时间:
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)
方法二:快捷函数
快捷函数在底层实现上是利用的是系统函数,但是会让你操作起来更加方便
判断文件类型:
In [27]: os.path.isdir('demo.bin')
Out[27]: False
In [28]: os.path.isfile('demo.bin')
Out[28]: True
判断文件最后访问时间:
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)
六、如何使用临时文件:
比如我们采集数据进行分析,但是我们只需要保存结果,我们采集的数据如果常驻内存就会让电脑崩溃,于是我们将这个数据放在临时文件中(外部存储),在文件关闭后将被删除
示例代码:
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
示例代码:
我们能看到文件路径
In [20]: nte = NamedTemporaryFile() In [21]: nte.name Out[21]: 'c:\\users\\k0rz3n\\appdata\\local\\temp\\tmpob51yb'
如果我们重新创建一个文件的话,原来的文件就会被关闭,关闭以后临时文件就会被自动删除,如果我们不想让他删除,我们在创建的时候就要设置一个参数
nte = NamedTemporaryFile(delete = False)
有需要Python学习资料的小伙伴吗?小编整理【一套Python资料、源码和PDF】,感兴趣者可以关注小编后私信学习资料(是关注后私信哦)反正闲着也是闲着呢,不如学点东西啦
相关推荐
- 阿里云国际站ECS:阿里云ECS如何提高网站的访问速度?
-
TG:@yunlaoda360引言:速度即体验,速度即业务在当今数字化的世界中,网站的访问速度已成为决定用户体验、用户留存乃至业务转化率的关键因素。页面加载每延迟一秒,都可能导致用户流失和收入损失。对...
- 高流量大并发Linux TCP性能调优_linux 高并发网络编程
-
其实主要是手里面的跑openvpn服务器。因为并没有明文禁p2p(哎……想想那么多流量好像不跑点p2p也跑不完),所以造成有的时候如果有比较多人跑BT的话,会造成VPN速度急剧下降。本文所面对的情况为...
- 性能测试100集(12)性能指标资源使用率
-
在性能测试中,资源使用率是评估系统硬件效率的关键指标,主要包括以下四类:#性能测试##性能压测策略##软件测试#1.CPU使用率定义:CPU处理任务的时间占比,计算公式为1-空闲时间/总...
- Linux 服务器常见的性能调优_linux高性能服务端编程
-
一、Linux服务器性能调优第一步——先搞懂“看什么”很多人刚接触Linux性能调优时,总想着直接改配置,其实第一步该是“看清楚问题”。就像医生看病要先听诊,调优前得先知道服务器“哪里...
- Nginx性能优化实战:手把手教你提升10倍性能!
-
关注△mikechen△,十余年BAT架构经验倾囊相授!Nginx是大型架构而核心,下面我重点详解Nginx性能@mikechen文章来源:mikechen.cc1.worker_processe...
- 高并发场景下,Spring Cloud Gateway如何抗住百万QPS?
-
关注△mikechen△,十余年BAT架构经验倾囊相授!大家好,我是mikechen。高并发场景下网关作为流量的入口非常重要,下面我重点详解SpringCloudGateway如何抗住百万性能@m...
- Kubernetes 高并发处理实战(可落地案例 + 源码)
-
目标场景:对外提供HTTPAPI的微服务在短时间内收到大量请求(例如每秒数千至数万RPS),要求系统可弹性扩容、限流降级、缓存减压、稳定运行并能自动恢复。总体思路(多层防护):边缘层:云LB...
- 高并发场景下,Nginx如何扛住千万级请求?
-
Nginx是大型架构的必备中间件,下面我重点详解Nginx如何实现高并发@mikechen文章来源:mikechen.cc事件驱动模型Nginx采用事件驱动模型,这是Nginx高并发性能的基石。传统...
- Spring Boot+Vue全栈开发实战,中文版高清PDF资源
-
SpringBoot+Vue全栈开发实战,中文高清PDF资源,需要的可以私我:)SpringBoot致力于简化开发配置并为企业级开发提供一系列非业务性功能,而Vue则采用数据驱动视图的方式将程序...
- Docker-基础操作_docker基础实战教程二
-
一、镜像1、从仓库获取镜像搜索镜像:dockersearchimage_name搜索结果过滤:是否官方:dockersearch--filter="is-offical=true...
- 你有空吗?跟我一起搭个服务器好不好?
-
来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。昨天闲的没事的时候,随手翻了翻写过的文章,发现一个很严重的问题。就是大多数时间我都在滔滔不绝的讲理论,却很少有涉及动手...
- 部署你自己的 SaaS_saas如何部署
-
部署你自己的VPNOpenVPN——功能齐全的开源VPN解决方案。(DigitalOcean教程)dockovpn.io—无状态OpenVPNdockerized服务器,不需要持久存储。...
- Docker Compose_dockercompose安装
-
DockerCompose概述DockerCompose是一个用来定义和管理多容器应用的工具,通过一个docker-compose.yml文件,用YAML格式描述服务、网络、卷等内容,...
- 京东T7架构师推出的电子版SpringBoot,从构建小系统到架构大系统
-
前言:Java的各种开发框架发展了很多年,影响了一代又一代的程序员,现在无论是程序员,还是架构师,使用这些开发框架都面临着两方面的挑战。一方面是要快速开发出系统,这就要求使用的开发框架尽量简单,无论...
- Kubernetes (k8s) 入门学习指南_k8s kubeproxy
-
Kubernetes(k8s)入门学习指南一、什么是Kubernetes?为什么需要它?Kubernetes(k8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用程序。它...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
慕ke 前端工程师2024「完整」
-
失业程序员复习python笔记——条件与循环
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
