Python-文件IO处理

目录文件处理

文件IO操作

函数说明
open打开
read读取
write写入
close关闭
readline多读取
readlines多行读取

1.open方法

open(file,mode=‘r’,buffering=1,encoding=None,error=None,newline=None,closefd=True,opener=None)

#
f = open('d:/python/test.txt') #打开一个文件
print (f.read()) #读取里面的内容
f.close()#关闭文件


文件操作中,最常用的就是读写,

文件访问的模式有两种, 一种是文本模式,一种是二进制模式,操作函数不尽相同,表现结果也不同.

windows使用codepage代码页,通俗易懂就是一页代码就是一个编码表,cp963等同于GBK.

1.open参数
1.file参数

打开或者想要创建的文件名,如果不指定路径那么就是当前路径

mode模式

模式描述字符意义
r缺省模式意思是只读
w只写打开
x创建并且写入一个新文件
a只写打开追加内容
b二进制模式
t缺省模式,文本模式
+读或写打开后追加权限,用来增加缺失的读写能力

模式对于IO来说,只有读写

  • r 读

  • wxa 只写

  • +增加

r模式

​ 只读模式,表示文件只是可读,如果写入数据会抛日常

​ 如果文件不存在也会抛异常

w模式

​ 表示只写模式,读取则会抛出异常

​ 文件不存在直接创建文件

​ 文件存在则清空文件内容

x模式

​ 文件不存在直接创建文件

​ 文件存在则抛出异常

a模式

​ 文件存在,只写打开,尾部追加内容

​ 文件不存在,创建文件打开只写,追加内容

wxa模式

​ w不管文件是否存在都会生成新的文件内容,

​ a尾部追加,不管文件存在不存在

​ x文件不存在则创建,所以必须文件不存在

文本模式t

​ 字符流,将文件的字节按照某种字符编码理解,按照字符操作.open的默认mode就是t.

二进制模式b

​ 字节流,将文件就按照字节理解,与字符编码无关,二进制模式操作时,字节操作使用bytes类型

+模式

​ 为 r,a,w,x进行追加,补齐缺失的功能.

​ +模式不能单独使用,认为他是为已存在的字符模式赋能

2.encoding:编码仅文本使用

none表示缺省编码,依赖操作系统windows,linux测试如下代码

f = open('d:/python/test.txt','w')
f.write('啊')
f.close()

linux 默认UTF-8而window使用GBK

3.文件指针

mode = r 指针起始为0

mode = a 指针在末尾 EOF

f = open('d:/python/test.txt','wb+')
print (f)
f.write(b'abc')
print (f.tell())
f.close()
#理解 w+二进制模式,写入模式+二进制

f = open('d:/python/test.txt','rt+')
f.write('啊')
print (hex(ord('啊')),'啊'.encode,'啊'.encode('gbk'))
print (f.tell())
f.close()
#理解R读模式+t文本模式

这两个模式都是覆盖的,他的起始点都是0,相当于开头

理解a模式

f = open('d:/python/test.txt','ba+')
print (f)
f.write(b'abc')
print (f.tell())
f.close()

f = open('d:/python/test.txt','ta+')
f.write('啊')
print (hex(ord('啊')),'啊'.encode,'啊'.encode('gbk'))
print (f.tell())
f.close()

a模式是尾部追加,起始点是EOF就是默认,观察文档,发现r读模式和a的区别

而且看上方案例发现第一次写入的是二进制的abc,那么如果追加的话会不会出问题?

我再放入一段代码请分析.

f = open('d:/python/test.txt','ba+')
print (f)
f.write(b'abc')
print (f.tell())
f.close()

f = open('d:/python/test.txt','ta+')
f.write('啊')
print (hex(ord('啊')),'啊'.encode,'啊'.encode('gbk'))
print (f.tell())
f.close()
#请分析这段代码是否有什么问题?
#00 00 00 00 00 00  
tell函数

tell()指定当前字节索引位置.

seek函数

seek(offset,whence=0)相对与某处进行偏移

文本模式
  • seek(0) 、seek(100),相对于右偏移,不可左超界.
  • seek(0,1),只能是偏移0, 原地踏步,无用操作
  • seek(0,2),只能是偏移0,就是跳到EOF末尾.
字节模式
  • seek(0)、seek(100),相对右偏移,不可超界
  • seek(0,1) 、seek(-5,1)、seek(5,1),相对当前索引位置偏移,不能左超界
  • seek(0,2)、seek(-5,2)、seek(5,2)相对EOF偏移,不能左超界

最常用的操作就是 seek(0),seek(0,2) 右偏移 和调到末尾

f = open('d:/python/test.txt','ta+')
f.write('啊')
print (hex(ord('啊')),'啊'.encode,'啊'.encode('gbk'))
print (f.tell())
print (f.seek(0,2))
f.close()
#-------------------------------------
f = open('d:/python/test.txt','ta+')
f.write('啊')
print (hex(ord('啊')),'啊'.encode,'啊'.encode('gbk'))
print (f.tell())
print (f.seek(0))
f.close()

2.read

读取字符,size=字符个数,附属或者none 表示EOF

filename = "d:/python/test.txt"
f = open(filename,'w+',encoding='gbk')
f.write("恭喜发财,红包拿来")
print (f.tell())
f.close()


f = open(filename)
print (1,f.read(1))
print (2,f.read(2))
print (3,f.read())
f.close()

f = open(filename,'wb+')
print (4,f.read(1))
print (5,f.read(2))
print (6,"恭喜发财,红包拿来".encode('gbk'))
print (7,f.read())
f.close()

请一定要指定编码类型,避免不必要的错误

3.write

write 文本模式时,从当前指针把字符串写入到文件中并且返回个数,二进制则是写入到字节中返回字节数.

writelines(lines),将字符串列表写入文件

filename = "d:/python/test.txt"
f = open("d:/python/test.txt",'w+',encoding="gbk")
lines = [ '123','456\n','\t',"恭喜发财" ]
f.writelines(lines) #插入后指针在哪? 是EOF还是0 
# f.seek(0)
print (f.read())
f.close()

思考 上端代码的指针问题,当执行 writelines后指针在哪呢?如果直接read 会读出什么来?

4.close

关闭文件对象,首先先flush刷新然后再关闭,可以查看文件的closed属性是否关闭

filename = "d:/python/test.txt"
f = open("d:/python/test.txt",'w+',encoding="gbk")
lines = [ '123','456\n','\t',"恭喜发财" ]
f.writelines(lines) #插入后指针在哪?
f.seek(0)
print (f.read())
print (f.closed)
f.close()
print (f.closed)

如果为True则为关闭,如果为False则为未关闭

上下文管理

1.上下文管理

文件对象这种打开必须要关闭的对象,为了保证他打开之后就一定会关闭的这个要求,提出了上下文的管理.

filename = "d:/python/test.txt"
with open(filename) as f :
    print  (1,f.closed)
    print  (2,f.write("abcd"))
print (f.closed)
#这段代码 wirte 会报错,not writable  没有写入权限

针对这个with 可以理解为

with 文件对象 as 标识符:   #你这里可以把文件对象 == 标识符,类似for i = 需要循环对象
    pass #标识符可以在内部使用

上下文管理with

1.使用with关键字,with针对的是with后的对象.

2.使用with … as 关键字.

3.上下文管理的语句并不会新的作用域.

文件对象上下文管理

1.进入with时,with后的文件对象是被管理的对象.

2.as后的语句是标识符,指向with后的文件对象, 文件对象 == 标识符.

3.with语句执行完成的时候,会自动关闭文件对象.

filename = "d:/python/test.txt"
with open(filename) as f :
    print  (1,f.closed)
    print  (2,f.write("abcd"))
print (f.closed)

f = open(filename)
with f as f2 :
    print (f is f2)
    print (f == f2)
    
#是否为True?

2.文件的遍历

类似日志文件,文件需要遍历,时间复杂度O(n),最常用则是逐行遍历.

filename = "d:/python/test.txt"
with open(filename,'w+',encoding='gbk') as f :
    f.write('\n'.join(map(str,(range(1,100)))))

with open(filename) as f :
    for lins in f :
        print (lins.encode('gbk'))

路径操作

1.os.path模块

从名称上看即为系统路径模块,

from os import path
p = path.join('/etc','sysconfig','network')
print (p,type(p))
#os.path 只针对str进行操作返回值也是str

print(path.exists(p)) #是否存在?
print(path.split(p)) #linux 分割
print (path.splitdrive('d:/python/test.txt')) #windows方法
print (path.dirname(p),path.basename(p)) #路径 和基名 可以理解为最后的文件名或者文件夹名称
print (path.abspath(''),path.abspath('.')) #路径 ''代表本路径  .也代表本路径
print ('*' * 20 )

p1 = path.abspath(__file__) #取当前绝对路径下的文件名称,即为test.py的绝对路径
print (p1)
while p1 != path.dirname(p1): #循环条件 p1绝对路径 不等于此文件的路径,如果等于则退出循环,
    p1 = path.dirname(p1) #做了一个赋值,将路径,赋值到p1,
    print (p1) #输出p1,至于为什么输出呈阶梯状可以理解以下dirname他每次取值都是要舍弃最后的基名的



#从此可以看出,os.path模块针对的都是str字符串类型.

2.path 类

python3.4 支持此pathlib的模块,使用path类操作目录

1.初始化
from pathlib import  Path
p = Path() #当前路径
print (p)
p = Path('a','b','c','d') #初始化生成
print (p)
p = Path('/etc',Path('sysconfig'),'network/ifcfg.cfg') #拼接
print (p)
2.拼接

操作符 /

path 对象/ path 对象

path对象/字符串

字符串/path对象

joinpath(*other)

joinpath路径上连接多个字符返回一个新的路径对象.

from pathlib import Path
p = Path()
print (p)
p = p / 'a'
p1 = 'b' / p
p2 = Path('c')
p3 = p2 / p1
print (p1,p2,p3)
print (p3.parts) #分解属性,将原有元素以原则的形式进行展示
print (p3.joinpath('d','e/f',Path('g/h')))
3.分解

parts属性,会返回各个目录的元组

from pathlib import Path
p = Path('/a/b/c/d')
print (p.parts)
#会输出什么?

4.父目录

parents 父目录,基于最后一个文件的上一个路径

from pathlib import Path
p = Path('/usr/local/source/pkg/mysql_5_7.tar.gz')
print (p.parents)
for i in p.parents:
    print (i)
5.目录组成部分

name,stem,suffix,suffixes,with_suffix(suffix),with_name(name)

name 目录的最后一个部分

suffix 目录中最后一部分的扩展名

stem 目录中最后一部分,没有后缀

name = stem + suffix

suffixes 返回多个拓展名列表

with_suffix(suffix) 有拓展名则替换,无则补充拓展名

with_name(name) 替换目录最后一部分,返回一个新的路径

from pathlib import  Path
p = Path('/data/apk/mysql/mysql_5_7.tar.gz')
print (1,p.name) #目录最后一部分
print (2,p.suffix) #目录最后一部分的扩展名
print (3,p.suffixes) #最后拓展名多个
print (4,p.with_name('redis')) #替换最后一部分,全部替换 
print (5,p.with_name('redis').with_suffix('.keep')) #替换最后一部分然后加入后缀
6.全局方法

cwd()返回当前工作目录

home() 返回当前家目录

from pathlib import  Path

p = Path('/data/apk/mysql/mysql_5_7.tar.gz')
print (p.cwd(),p.home())

7.判断方法

exists()目录或者文件是否存在

is_dir() 是否是目录,目录存在则返回True

is_file() 是否为普通文件,文件存在返回True

is_symlink() 是否是软连接

is_socket() 是否为socket 连接文件.

is_block_device() 是否为块存储设备.

is_char_device()是否为字符设备

is_absolute() 是否为绝对路径

文件只有存在才可以判断文件属性

from pathlib import  Path
p = Path('d:/python/test.txt')

print (p.cwd(),p.home())
print (p.exists())
print (p.is_dir())
print (p.is_file())
print (p.absolute())
print (p.is_block_device())
print (p.is_symlink())
print (p.is_socket())
print (p.is_char_device())
8.绝对路径

resolve() 非windows,返回一个新的路径,新路径基于当前path的绝对路径,如果是软连接则被直接解析.windows 下无效果

absolote() 获取绝对路径.

from pathlib import  Path
p = Path('test.py')
print (p.resolve())
print (p.absolute())
9.其他操作

rmdir 删除空目录,没有提供判断方法

touch (mode=0o666,exist_ok=True) 创建一个文件

as_uri() 将路径返回成url

mkdir(mode = 0o777,parents=false,exist_ok=flase)

parents 即为mkdir -p 创建父目录,父目录不存在时抛出异常filenofoundError

exist_ok=false 路径存在抛异常,true 则忽略

iterdir()迭代当前目录

from pathlib import  Path

p = Path('d:/python/a/b/c/d')
p.mkdir(parents=True,exist_ok=True)
(p / 'test').touch()
p1 = p.parents[len(p.parents) -3 ] #索引
print (p1)
for x in p.parents[len(p.parents) -1 ].iterdir(): #-1为目录索引
    if x.is_dir():
        print ('dir = ',x )
    elif x.is_file():
        print ('file = ',x)
    else:
        print ('other',x)


10.通配符

glob(pattern) 通配指定模式,返回生成器对象

rglob(pattern) 通配指定模式,递归目录,返回生成器对象.

?代表一个字符

*代表任意字符

[abc]或者[a-z]表示一个字符

from pathlib import  Path

p = Path("d:/python")

l1 = list(p.glob("test"))
l2 = list(p.glob("*.py"))
l3 = list(p.glob("**/*.py"))

g = p.rglob('*.py')
#next(g)
l4 = list(p.rglob("*.???"))
l5 = list(p.rglob('[a-z]*.???'))
print (1,l1,sep='\n')
print (2,l2,sep='\n')
print (3,l3,sep='\n')
print (4,l4,sep='\n')
print (5,l5,sep='\n')

3.shuitl 模块

文件拷贝:使用两个文件对象,读取源文件内容,写入目标文件中完成拷贝.这样会都是stat数据信息元数据,因为不会复制着一些数据.

python提供了方便的shuitl模块.

copy复制

follow_symlinks 复制权限!!!

copyfileobj(fsrc,fdst[,length])

文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容fdst要求可写,length制定了buffer的大小.

copyfile(src,dst,*,follow_symlinks=True)

复制文本内容,不含元数据.src、dst为文件的路径字符串.

本质上就是调用copyfileobj,所以不带元数据二进制内容复制.

copymode(src,dst,*,follow_symlinks=True)

仅仅复制权限

copystat(src,dst,*,follow_symlinks=True)

复制元数据

copy(src,dst,*,follow_symlinks=True)

复制文件内容,权限和元数据不报考修改时间和创建时间

本质上调用copyfile 和copymode

copy2比copy多了元数据全部复制,需要平台支持

本质调用copyfile 和copystat

copytree(src,dst,symlinks=False,ignore=None,copy_function=copy2,ignore_dangling_symlinks=False)

递归复制目录,使用copy2,也就是带更多的元数据进行复制,

src和dst必须是目录,src源必须存在,dst必须不存在

ignore = func ,提供一个callable(src,name) ->ignored_name,意思就是提供一个可调用的src源和名称,names就是os.listdir的结果,就是src的文件名,多个,返回值是要被过滤的文件名集合类型数据.

import shutil


def ignore(src, names):
    ig = filter(lambda x: x, names)
    return set(ig)
print (shutil.copytree('d:/python/test1','d:/python/test4',ignore=ignore))
删除 rm
shutil.rmtree(path,ignore_error=False,onerror=None)

递归删除,如果rm -rf 一样,危险慎用

他不是原子操作有可能误删,中断后已经删除文件不可恢复.

ignore_error = False 忽略报错 当false或者omttied时onerror

onerror为callable(可以调用对象),接受function(函数),path,execinfo.

shutil.rmtree('d:/python/test1')
移动 mv

move(src,dst,copy_function=copy2)

递归移动文件,目录到目标,返回目标

本身使用是os.rename方法(系统重命名)

如果不支持os.rename,则使用copytree在删除目录

默认使用copy2方法

import shutil

print (shutil.move('d:/python/test1','d:/python/test2'))
print (os.rename('d:/python/test2','d:/python/test3'))
print (os.rename('d:/python/test3','d:/python/test4'))
ake_archive(base_name, format, root_dir=None, base_dir=None,owner=None, group=None, logger=No



* 参数详解

* base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,

* format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”

* root_dir: 要压缩的文件夹路径(默认当前目录)

* owner: 用户,默认当前用户

* group: 组,默认当前组

* logger: 用于记录日志,通常是logging.Logger对象

* 案例1:将 /data下的文件打包放置当前程序目录

import shutil


shutil.make_archive("d:/python/test10",'gztar',root_dir='d:/python/')

练习此文档大概需要练习的代码

filename = "d:/python/test.txt"
with open(filename,'w+',encoding='gbk') as f :
    f.write('\n'.join(map(str,(range(1,100)))))
with open(filename) as f :
    for lins in f :
        print (lins.encode('gbk'))


filename = "d:/python/test.txt"
with open(filename,'w') as f :
    print  (1,f.closed)
    print  (2,f.write("abcd"))
print (f.closed)

f = open(filename)
with f as f2 :
    print (f is f2)
    print (f == f2)

from os import path
p = path.join('\etc','sysconfig','network','ifconfig.cfg')
print (p,type(p))

print(path.exists(p)) #是否存在?
print(path.split(p)) #linux 分割
print (path.splitdrive('d:/python/test.txt')) #windows方法
print (path.dirname(p),path.basename(p)) #路径 和基名 可以理解为最后的文件名或者文件夹名称
print (path.abspath(''),path.abspath('.')) #路径 ''代表本路径  .也代表本路径
print ('*' * 20 )
p1 = path.abspath(__file__) #取当前绝对路径下的文件名称,即为test.py的绝对路径
print (p1)
while p1 != path.dirname(p1): #循环条件 p1绝对路径 不等于此文件的路径,如果等于则退出循环,
    p1 = path.dirname(p1) #做了一个赋值,将路径,赋值到p1,
    print (p1) #输出p1,至于为什么输出呈阶梯状可以理解以下dirname他每次取值都是要舍弃最后的基名的

from pathlib import  Path
p = Path()
print (p)
p = Path('a','b','c','d')
print (p)
p = Path('/etc',Path('sysconfig'),'network/ifcfg.cfg')
print (p)


from pathlib import Path
p = Path()
print (p)
p = p / 'a'
p1 = 'b' / p
p2 = Path('c')
p3 = p2 / p1
print (p1,p2,p3)
print (p3.parts) #分解属性,将原有元素以原则的形式进行展示
print (p3.joinpath('d','e/f',Path('g/h')))



from pathlib import Path
p = Path('/a/b/c/d')
print (p.parts)



from pathlib import Path
p = Path('/usr/local/source/pkg/mysql_5_7.tar.gz')
print (p.parents)
for i in p.parents:
    print (i)


from pathlib import  Path
p = Path('/data/apk/mysql/mysql_5_7.tar.gz')
print (1,p.name) #目录最后一部分
print (2,p.suffix) #目录最后一部分的扩展名
print (3,p.suffixes) #最后拓展名多个
print (4,p.with_name('redis')) #替换最后一部分,全部替换
print (5,p.with_name('redis').with_suffix('.keep')) #替换最后一部分然后加入后缀


from pathlib import  Path
p = Path('d:/python/test.txt')
print (p.cwd(),p.home())
print (p.exists())
print (p.is_dir())
print (p.is_file())
print (p.absolute())
print (p.is_block_device())
print (p.is_symlink())
print (p.is_socket())
print (p.is_char_device())

from pathlib import  Path
p = Path('test.py')
print (p.resolve())
print (p.absolute())

from pathlib import  Path

p = Path('d:/python/a/b/c/d')
p.mkdir(parents=True,exist_ok=True)
(p / 'test').touch()
p1 = p.parents[len(p.parents) -3 ]
print (p1)
for x in p.parents[len(p.parents) -1 ].iterdir(): #-1为目录索引
    if x.is_dir():
        print ('dir = ',x )
    elif x.is_file():
        print ('file = ',x)
    else:
        print ('other',x)

from pathlib import  Path

p = Path("d:/python")

l1 = list(p.glob("test"))
l2 = list(p.glob("*.py"))
l3 = list(p.glob("**/*.py"))

g = p.rglob('*.py')
#next(g)
l4 = list(p.rglob("*.???"))
l5 = list(p.rglob('[a-z]*.???'))
print (1,l1,sep='\n')
print (2,l2,sep='\n')
print (3,l3,sep='\n')
print (4,l4,sep='\n')
print (5,l5,sep='\n')
import os
import shutil


def ignore(src, names):
    ig = filter(lambda x: x, names)
    return set(ig)
print  (shutil.copytree('d:/python/test1','d:/python/test4',ignore=ignore))


import shutil

print (shutil.move('d:/python/test2.tar.gz','d:/python/test2.zip'))
print (os.rename('d:/python/test2','d:/python/test3'))
print (os.rename('d:/python/test3','d:/python/test4'))

shutil.make_archive("d:/python/test10",'gztar',root_dir='d:/python/')
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值