#读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),
# 然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
try:
#如果文件不存在,open()函数就会抛出一个IOError的错误
#相对路径为当前py文件路径
file=open('error.log','r')
#read()方法可以一次读取文件的全部内容,
# Python把内容读到内存,用一个str对象表示:
text=file.read()
print(type(text))
print(text)
except IOError as e:
print(e)
finally:
#文件使用完毕后必须关闭
if file:
file.close()
#简化写法,自动执行close
#读取文本文件,并且是UTF-8编码的文本文件
with open('error.log','r') as file:
# read()会一次性读取文件的全部内容
# read(size)方法,每次最多读取size个字节的内容。
# 调用readline()可以每次读取一行内容,
# 调用readlines()一次读取所有内容并按行返回list
#再同一个文件下以上read/write方法共享一个文件指针,当前read方法从前一个read方法的结束指针处开始读文件,
#当text=='' 时表示文件已经读完。
text = file.read()
print(type(text))
print(text)
text = file.read(1024)
print(type(text))
print(text)
text = file.readline()
print(type(text))
print(text)
text = file.readlines()
print(type(text))
print(text)
#open()函数返回的这种有个read()方法的对象,不要求从特定类继承,只要写个read()方法就行。
#要读取二进制文件,比如图片、视频等等,用'rb'模式
#要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数
#在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。
with open('pink.png','rb') as file:
pass
with open('error.log','r',encoding='GBK',errors='ignore') as file:
pass
#调用open()函数时,传入标识符要可写文件权限
#读写都会移动文件指针。获得指针位置:file.tell() ,设置指针位置:file.seek(0)
# r 只读文件,打开文件后指针位于0,文件不存在会报错。rb 二进制读文件。
# r+ 可读可写,打开文件后指针位于0,读为从当前指针出开始到结尾,写为从当前指针出开始写逐个字符覆盖原先内容,读写文件时不会创建不存在的文件,会报错.
# rb+ 二进制格式读写文件,打开文件后指针位于0,文件不存在会报错。
# w只写文件,打开文件后指针位于0,在打开文件后原先内容即被清空,从头开始写。如果该文件不存在,创建新文件。 wb+ 二进制读写文件。
# w+ 读写文件,打开文件后指针位于0,在打开文件后原先内容即被清空,从头开始写,读为从当前指针出开始到结尾。写文件时如果该文件不存在,创建新文件。
# a 只追写文件,打开文件后指针位于end,写为从end开始写.不存在则创建 ,ab+ 追读写二进制。
# a+ 读 追写文件。打开文件后指针位于end,写为从end开始写,读为从当前指针出开始到结尾, 读写文件时不存在则创建。
with open('error.log','a+') as file:
print('--------------------------------')
print(file.tell())
file.seek(0)
print(file.readlines())
file.write('fuck
')
print(file.tell())
#当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
# 只有调用close()/flush()方法时,操作系统才保证把没有写入的数据全部写入磁盘。
# 忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:
print('--------------------------')
#,数据读写不一定是文件,也可以在内存中读写。
from io import StringIO ,BytesIO
#写str
f = StringIO('Hello!
Hi!
Goodbye!')
#逐字覆盖式写入
#f.write('fuck')
while True:
s = f.readline()
if s == '':
break
print(s)
#写bytes
f = BytesIO('中文'.encode('utf-8'))
#逐字覆盖式写入
#f.write(bytes(22))
print(f.getvalue())
import os
#操作系统类型
print(os.name)
#环境变量
env_info=os.environ
print(type(env_info))
print(env_info.get('ALLUSERSPROFILE','default value'))
# 查看当前目录的绝对路径:
current_path=os.path.abspath('.')
print(current_path)
#把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符。
full_path=os.path.join(current_path, 'testdir')
print(type(full_path),full_path)
# 然后创建一个目录,若存在则报错
os.mkdir(full_path)
# 删掉一个目录:
os.rmdir(full_path)
# 对文件重命名:
os.rename('G:\Python\PycharmProject\learn_python\FileIO\fuck.py', 'fuckme.py')
# 删掉文件:
os.remove('G:\Python\PycharmProject\learn_python\FileIO\fuckme.py')
#把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名,前一部分为剩余信息:
print(os.path.split(full_path))
#得到文件扩展名:('/path/to/file', '.txt')
print(os.path.splitext('/path/to/file.txt'))
import shutil
#复制文件,fsrc(可读),fdst(可写)都是文件对象,都需要打开后才能进行复制操作
f1=open('error.log','r')
f2=open('name_copy.log','w+')
shutil.copyfileobj(f1,f2)
#复制文件,fsrcpath,fdstpath,只修改文件内容,不修改书写权限与文件状态。
shutil.copyfile('error.log','name_copy_2.log')
#仅copy 读写权限,不更改文件内容,组和用户。frspath,dstpath
#shutil.copymode('error.log','name_copy.log')
# 复制所有的状态信息,包括权限,组,用户,时间等
#shutil.copystat(srcpath,dstpath)
#复制文件的内容以及权限,先copyfile后copymode
#shutil.copy(srcpath,dstpath)
# 复制文件的内容以及文件的所有状态信息。先copyfile后copystat
#shutil.copy2(srcpath, dstpath)
#递归的复制文件夹内容及读写权限,文件状态
shutil.copytree('src', 'dst')
#递归地删除文件夹
shutil.rmtree('dst')
# 递归的移动文件夹/文件,目标文件夹/文件不存在就创建
shutil.move('src', 'dst')
# 压缩打包
#base_name:压缩打包后的文件名或者路径名,忽略压缩扩展名。
#format:压缩或者打包格式 "zip", "tar", "bztar"or "gztar"
#root_dir : 将哪个目录或者文件打包(也就是源文件)
shutil.make_archive('dst', 'zip', root_dir='dst')
#列出路径下所有文件夹与文件,返回list[str]
type(os.listdir('.'))
#判断是否是文件夹
print(os.path.isdir('dst'))
#判断是否是文件
print(os.path.isfile('dst.zip'))
#列出当前路径下所有.py文件
print([x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py'])
#把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling
#序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
#反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
#pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:
import pickle
d=dict(A='a',B='b')
f = open('dump.txt', 'wb')
pickle.dump(d, f)
f.close()
import pickle
# pickle.dumps(object)方法把任意对象序列化成一个bytes
# pickle.dump(object,f)直接把对象序列化后写入一个file-like Object:
with open('dump.txt', 'wb') as f:
d = dict(A='a', B='b')
print(d)
pickle.dump(d, f)
# pickle.loads(bytes)方法反序列化出对象
# 用pickle.load(f)方法从一个file-like Object中直接反序列化出对象。
with open('dump.txt', 'rb') as f:
d = pickle.load(f)
print(d)
# 这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。
# 可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据。
# 更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。
# JSON类型 Python类型
# {} dict
# [] list
# "string" str
# 1234.56 int或float
# true/false True/False
# null None
# obj-(obj2dict())->dict-->str
# str-->dict-(dict2obj())->obj
# 这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。
# json.dumps(object)方法可以把一个可序列化对象返回一个str,内容就是标准的JSON。类似的,dump(object,file)方法可以直接把JSON写入一个file-like Object。
# 要把JSON反序列化为Python对象,用loads(str)或者对应的load(file)方法,前者把JSON的字符串反序列化,后者从file-like Object中读取字符串并反序列化:
import json
print('---------------------')
d = dict(A='a', B='b')
print(d)
dict_str = json.dumps(d)
print(dict_str)
d = json.loads(dict_str)
print(d)
# 非dict类序列化
class Stu(object):
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
def __str__(self):
return 'name:%s,age:%s,score:%s' % (self.name, self.age, self.score)
# 对于非dict对象要定义一个函数将对象转化为一个dict,或者使用对象自带方法,object.__dict__方法(也有少数例外,比如定义了__slots__的class。)
def stu2dict(stu):
return dict(name=stu.name, age=stu.age, score=stu.score)
stu = Stu('huang', 22, 88)
print(stu)
stu_str = json.dumps(stu, default=stu2dict)
print(stu_str)
stu_str = json.dumps(stu, default=lambda ob: ob.__dict__)
print(stu_str)
# 同样要定义一个方法完成dist->obj
def dict2stu(d):
return Stu(d['name'], d['age'], d['score'])
stu = json.loads(stu_str, object_hook=dict2stu)
print(stu)