# 上周内容回顾
# 单位换算 :
# 8bit = 1Bytes
# 1024Bytes = 1KB
# 1024KB = 1MB
# 1024MB = 1GB
# 1024GB = 1TB
# 1024TB = 1PB

# 字符编码
# 字符编码的发展史
# 字符编码表
# ASCII码 只有英文字母和符号与数字的对应关系
# 用8位二进制(1bytes)表示一个英文字符
#
# GBK:中文 英文 符号与数字对应关系
# 用2bytes表示一个中文符号 兼容英文字符
#
# 乱码: 编码与解码不一致
# 保证不乱码的核心: 当初以什么编码存的(encode) 就以什么编码取(decode)
# 内存中unicode >>>编码(encode) 硬盘中utf-8编码
# 硬盘中utf-8编码 >>>解码(decode) 内存中的unicode
#
# 现在的计算机内存中统一用的都是unicode
# unicode两大特点:
# 1.用户无论输入哪个国家的字符都能够正常显示(兼容万国)
# 2.与任意国家的编码都有对应关系
#
# 文件头
# # coding:gbk
# 指定python解释器读取该文件使用gbk编码,而不再用默认的
#
# python2在读取文件默认使用的是ASCII码
# python3在读取文件默认使用的是utf-8码
#
# 识别python语法执行python代码 x = '上'
#
# python2 如果不指定文件头 中文没法存储 那是因为python2解释器识别语法存储数据的时候默认使用的是ASCII
# 如果指定了文件头 python2解释器识别语法存储数据的时候使用文件头指定的编码
#
# python2中通常都会在中文的字符串前面加一个u
# x = u'上'
# 告诉python2解释器将上存成unicode的形式
# python3 里面的字符串直接存成unicode(******)
#
#
# x = '上'
# # 第一种转换方式
# res1 = bytes(x,encoding='utf-8') # 用 bytes()转换成二进制的bytes类型,需要指定编码格式
# print(res1,type(res1)) # 结果为 b'\xe4\xb8\x8a' <class 'bytes'>
# res2 = str(res1,encoding='utf-8') # 用 str() 可以将二进制bytes类型转换为 字符串,需要指定编码格式
# print(res2,type(res2)) # 结果为 上 <class 'str'>
#
# # 第二种转换方式
# x = '上'
# res = x.encode('utf-8') # 编码成二进制格式 就是bytes格式 也可以用上一个方法转换成二进制类型
# print(type(res)) # 结果为 <class 'bytes'>
# print(res.decode('utf-8')) # 解码成 原格式 上
#
# 文件处理
# 一套完整的计算机系统
# 应用程序
# 操作系统
# 计算机硬件
#
# 什么是文件
# 操作系统暴露给用户操作复杂硬盘的简易接口
#
# python代码操作文件
# f = open(文件路径,mode='读写模式',encoding='utf-8')
# f.close()
# print(f)
#
# f:遥控器 文件句柄 文件对象
#
# 文件的上下文管理,with打开后执行完下面子代码块会自动close文件
# with open(....) as f:
# 文件操作
#
# 文件路径
# 相对路径:必须有一个参照物 通常是相对于执行文件所在的文件夹
# 绝对路径:类似于GPS全球定位,不需要有任何的参照物
# r用来取消转义
# r'D:av\ttt\xxx\ooo\rrr'
#
# mode不写默认用的是rt
#
# encoding参数只在mode为 t 文本模式的情况下才加
#
# 文件读写模式
# r:只读模式
# 1.文件不存在的情况下 直接报错
# 2.文件存在的情况下 光标在文件开头
# w:只写模式
# 1.文件不存在的情况下 自动创建新文件
# 2.文件存在的情况下 先清空文件内容再执行写入
# a:只追加模式(只能在文件末尾添加内容)
# 1.文件不存在的情况下 自动创建新文件
# 2.文件存在的情况下 光标直接在文件末尾
#
# 文件操作单位
# t:文本模式
# 只能和r/w/a连用 并且不写的情况下 默认就是t
# b:原生的二进制数据
# 只能和r/w/a连用
# 该模式通常用来处理非文本文件
# 直接存储网络上传输过来的二进制数据
#
# 有钱就买Mac
#
# f.read() 一次性将文件内容全部读到内存
# 当文件过大的情况下该方法可能会导致内存溢出
#
# f.readline():一行行的读取内容
#
# 文件句柄f可以直接被for循环 每次for循环拿出来的就是文件一行行的内容
# for line in f:
# print(line)
#
# \r\n:换行符 现在做了优化 可以只写\r或者\n
#
# f.readlines():将文件一行行的内存放是列表中 成为一个个元素
#
# f.readable():是否可读
#
# f.write() 写文件
#
# f.writeable() 是否可写
#
# f.writelines() 要接收一个容器类型
# for i in l:
# f.write(i)
#
# f.writeline() 写一行
#
# 今日内容
# 其他模式补充
# r+
# w+
# a+
#
# 控制文件内光标的移动
#
# 实时监测文件内容变化
#
#
# 文件修改
# 两种方式(******)
#
# 函数简介
# 函数的前戏 函数的定义
# 函数的返回值



"""
r
w
a
将上面的三个模式称为纯净模式
r+
w+
a+
"""
# with open(r'test',mode='r+',encoding='utf-8') as f: # 如果当前目录下没有test 会直接报错
# print(f.readable()) # 用r+打开文件 文件为可读 True
# print(f.writable()) # 用r+打开文件 文件为可写 True
# print(f.readline()) # 读取一行,第一行数据,光标在第一行末尾,再进行写操作,会写在文件末尾
# f.write('嘿嘿嘿') # 在最后一行添加 字符串,多次执行,会追加多次
# # 如果当前目录下没有test 会直接报错 FileNotFoundError: [Errno 2] No such file or directory: 'test'
# # r+模式打开的文件 可读可写,写的时候是追加写


# with open(r'test',mode='w+',encoding='utf-8') as f:
# print(f.readable()) # 用r+打开文件 文件为可读 True
# print(f.writable()) # 用r+打开文件 文件为可写 True
# f.write('嘿嘿嘿')
# # w+ 打开文件之后,如果文件存在,会先清空文件,然后可以读可以写
# # w+ 打开文件之后,如果文件不存在,会先创建这个文件
# # w+ 打开文件之后,写文件会覆盖文件之前有的内容,如果文件不存在则会创建一个文件

# with open(r'test',mode='a+',encoding='utf-8') as f:
# print(f.readable()) # 用r+打开文件 文件为可读 True
# print(f.writable()) # 用r+打开文件 文件为可写 True
# print(f.readline()) # a+模式打开文件,光标在文件末尾,不会读取出数据来
# f.write('嘿嘿嘿') # 在最后一行添加 字符串,多次执行,会追加多次

# with open(r'test',mode='r+b') as f: # b模式下不能指定编码格式,因为就是取二进制数据,不需要解码操作
# print(f.readable()) # 用r+b打开文件 文件为可读 True
# print(f.writable()) # 用r+b打开文件 文件为可写 True
# res = f.read() # 读取的文件内容赋值给res
# print(res,type(res)) # 读取到bytes类型的二进制数据 <class 'bytes'>
# print(res.decode('utf-8')) # 用utf-8解码二进制数据,python3终端默认就是utf-8格式,可以得到原内容
# res1 = str(res,encoding='utf-8') # 用字符串格式转换(utf-8编码二进制数据后的数据)可以得到字符串即原内容
# print(res1) # 可以得到字符串即原内容




# 文件内 光标的移动
# # 在rt模式下 read内的数字 表示的是字符的个数,不是字节,因为是文本模式,读出来的都是汉字或者英文字符,不会是二进制
# # 除此之外,数字表示的都是字节 read(),这里括号中的数字都是表示字节数,即bytes数量 编码格式不同,字符和字节对应的数量不同
# with open(r'test','r',encoding='utf-8') as f:
# print(f.read(5)) # mode没有写,默认是rt模式,这个5 就是五个汉字或者五个英文字符这样的字符

# with open(r'test','rb') as f:
# res = f.read(9) # 二进制模式下,读的是九个字节bytes
# print(res) # 结果为 b'\xe5\x98\xbf\xe5\x98\xbf\xe5\x98\xbf\xe5'
# print(res.decode('utf-8')) # 如果res这九个二进制正好是九个汉字即可以显示内容,否则报错,解码不全,不可解码
# # 文档中都为汉字,utf-8编码格式下三个bytes代表一个汉字,读9个bytes就是三个汉字,读10个bytes就会报错



# 文件内光标的移动
"""
f.seek(offset,whence) f.seek(偏移数,参照数值)
seek移动都是字节数
offset:相对偏移量 光标移动的字节数bytes,不是字符
whence:
0:参照文件的开头 t和b都可以使用
1:参照光标所在的当前位置 只能在b模式下用
2:参照文件的末尾 只能在b模式下使用
"""
# with open(r'test','rt',encoding='utf-8') as f:
# print(f.read(1)) # rt模式下,read()括号中的数字表示字符,汉字或者、英文字符的字符数
# f.seek(6,0) # seek移动都是字节数,文本全为汉字,6表示偏移6个bytes,在utf-8编码格式下表示两个汉字
# # 即表示,从文件开头为参照,光标向右偏移六个bytes,两个字符,后面的读取read操作,从第二个字开始往后读取
# # f.seek(4,0) # seek移动都是字节数,因为都是汉字,在utf-8编码格式下3个bytes表示1个汉字,偏移4个bytes,不完整会报错
# print(f.read(1)) # 读取的为第三个字,上述操作后从光标移动到的第二个字符后开始,rt模式下,读取一个字符(汉字或者英文0
# f.seek(0,0) # 即表示,从文件开头为参照,光标向右偏移0个bytes
# print(f.read(1)) # 即表示,读取第一个字符(汉字,英文--因为是在rt模式下)
# f.seek(0, 0) # 即表示,重新移动光标,从文件开头为参照,光标向后偏移0个bytes
# print(f.read(1)) # 即表示,读取第一个字符(汉字,英文--因为是在rt模式下)
# f.seek(6,0) # 即表示,从文件开头为参照,光标向右偏移六个bytes,光标移动到这里
# print(f.read()) # read括号中不指定字符数量,默认全部读取



# with open(r'test','rb') as f: # 用二进制只读模式打开,里面内容都是字节的二进制,bytes类型
# print(f.read(3).decode('utf-8')) # 读取三个字节,进行utf-8解码,utf-8格式下三个bytes为一个字符,即打印第一个字符(汉字)
# f.seek(0,0) # 移动光标,第一个0向右偏移量为0个字节,第二个0 以文件开头为参照
# print(f.read(3).decode('utf-8')) # 读取三个字节,utf-8下表示一个字符(汉字),用utf-8解码,得到第一个字符(汉字,字母)
# # f.seek(7,0) # 移动光标,向右移动七个字节,7个bytes,以文件开头为参照,utf-8下,表示两个多汉字,第三个汉字编码不完整
# # print(f.read(1).decode('utf-8')) # 读取编码不完整的二进制,bytes数据,解码会报错
# f.seek(6,0) # seek移动都是字节数 向右偏移6个bytes,以文件开头为参照
# # f.seek(4,0) # seek移动都是字节数 向右偏移4个bytes,以文件开头为参照

# with open(r'test','rb') as f: # 用二进制只读模式打开,里面内容都是字节的二进制,bytes类型
# print(f.read(3).decode('utf-8')) # 读取三个字节,进行utf-8解码,utf-8格式下三个bytes为一个字符,即打印第一个字符(汉字)
# f.seek(3,1) # 移动光标,第一个3 向右偏移量为3个字节,第二个1 以当前光标位置为参照,前面读取了前三个bytes,当前光标在第三个bytes后
# print(f.read(1)) # 光标再向右移动一个字符(三个字节),读取一个字符,即为第三个汉字
# f.seek(6,0) # seek移动都是字节数 偏移6个bytes,以文件开头为参照
# f.seek(4,0) # seek移动都是字节数 偏移4个bytes,以文件开头为参照


# with open(r'test','rb') as f: # 用二进制只读模式打开,里面内容都是字节的二进制,bytes类型
# print(f.read()) # 读取结果为全文二进制bytes类型数据
# f.seek(-3,2) # 移动光标,第一个-3 向左偏移量为3个字节,第二个2 以文件末尾位置为参照,
# print(f.read().decode('utf-8')) # 即在文件末尾 向左读取三个bytes,一个字符的数据,并解码 得到文件最后一个字符(汉字)

# with open(r'test','r+',encoding='utf-8') as f: # 以r+模式打开文件
# f.seek(3,0) # 移动光标,第一个3 向右偏移量为3个字节,第二个0 以文件开头位置为参照
# f.write('过') # 即光标在 第一个字符(前三个bytes后),写入一个字符'过'


# # 案例 添加时间模块,记录文件改变内容
# import time # (导入时间模块,后面会学到)
# res = time.strftime('%Y-%m-%d %X') # 调用时间模块,取值时间,赋值给变量res
# print(res,type(res)) # 打印结果为时间,,类型为字符串类型 2019-07-08 16:43:57 <class 'str'>
# #
# with open(r'test01.txt','a',encoding='utf-8') as f: # 追加模式下打开一个文件,文件不存在则创建一个
# f.write('%s egon给jason发了1个亿的工资\n'%res) # 追加写入内容,时间为字符串,用占位符做字符串拼接
# # 文件中显示内容为 2019-07-08 16:10:46 egon给jason发了1个亿的工资


# # 案例 如果文件发生新增,则打印新增内容
# with open(r'test01.txt','rb') as f: # 以二进制模式打开文件
# # 因为需要通过移动光标来判断是否有新增,光标的移动单位是字节bytes二进制
# f.seek(0,2) # 先将光标移动到文件末尾,0表示向右偏移位为0,2表示以文件末尾为参照,即将光标移动到文件末尾
# while True: # 创建循环,循环监测文件是否改变
# res = f.readline() # 读取一行内容,因为光标已经在循环外移动到了文件末尾,所以没有新增则读不出内容
# # print(f.tell()) # 560 # 查看光标移动了多少位 bytes
# if res: # 字符串自带布尔值,如果res这个变量有值,则为True,则会运行一下代码,打印新增时间和内容
# print("新增的文件内容:%s"%res.decode('utf-8')) # 用占位符拼接字符串,打印新增时间和新增内容res
# # 说明有人操作当前文件
# else: # 其他条件下,说明文件没有被任何人操作
# print('暂无其他人操作该文件')


# # 阶段截断文件
# with open(r'test','a',encoding='utf-8') as f: # 以追加模式打开文件,w模式会清空文件,r模式为只读模式
# f.truncate(6) # 接收的字节的长度 整型 调用截断方法truncate()括号中需要输入整型数据类型,表示截断字节数
# # 截断6和字节,即表示截断两个字符,留下个字节,留下两个字符,剩余的全部删除
# # 保留0~6字节数 后面的全部删除(截断)



with open(r'test','r+',encoding='utf-8') as f: # 以r+模式打开文件
f.seek(6,0) # 移动光标,向有移动6个字节,6个bytes,0表示以文件开头为参照,即从文件开头向右移动6个字节,两个字符
f.write('h') # 从文件开头向右移动6个字节,两个字符,在前两字后面写入'h'


# # 修改文件的两种方式 ----需要默写----
# # 修改文件的方式1
# # 先将数据由硬盘读到内存(读文件)
# # 在内存中完成修改(字符串的替换)
# # 再覆盖原来的内容(写文件)
# with open(r'test02.txt','r',encoding='utf-8') as f: # 只读模式打开一个文件
# data = f.read() # 将文件全部内容一次读出,赋值给一个变量data
# print(data) # 打印data
# print(type(data)) # 数据类型为 <class 'str'> 字符串
# #
# with open(r'test02.txt','w',encoding='utf-8') as f: # 再以只写模式打开这个文件
# res = data.replace('123','xiao') # 将原来取出的数据(赋值给变量的数据)修改后赋值给res
# print(data) # 查看data,没有变化,因为字符串为不可变类型
# f.write(res) # 将新变量(修改值后赋值给的变量),先清空文件,再写入文件,修改成功
# # 达到修改的目的,用户无感知,速度比较快,现象为文件被修改复写成功

"""
优点:任意时间硬盘上只有一个文件 不会占用过多硬盘空间
缺点:当文件过大的情况下,可能会造成内存溢出
"""


# 文件修改方式2
# 创建一个新文件
# 循环读取老文件内容到内存进行修改 将修改好的内容写到新文件中
# 将老文件删除 将新文件的名字改成老文件名
import os # 系统模块,思路是修改数据写到新文件中后,删除源文件,修改新文件名,达到修改文件的目的
with open(r'test02.txt','r',encoding='utf-8') as read_f,open(r'test02.swap','a',encoding='utf-8') as write_f:
# 以只读方式打开需要被修改的文件
# 以追加模式打开一个新文件,新文件不存在则创建
for line in read_f: # 循环从源文件中读出每一行内容
new_line = line.replace('xiao','123') # 修改从源文件取出的一行数据,赋值给新变量
write_f.write(new_line) # 循环将新变量写入新文件
os.remove('test02.txt') # 调用系统模块删除源文件
os.rename('test02.swap','test02.txt') # 调用系统模块修改新文件名,改为源文件,达到修改文件的目的
# os.remove('文件名')
# os.rename('旧文件名','新文件名')

"""
优点:内存中始终只有一行内容 不占内存
缺点:再某一时刻硬盘上会同时存在两个文件

每日默写
修改文件的两种方式
加上你自己的逻辑思维
"""




# 函数入门
# # 计算长度 除了len()方法以外,设置变量用for循环取值,变量记录循环次数,每次自增长1,打印变量
# s = 'hello'
# print(len(s))
# # 假设没有len了

# 设置变量用for循环取值,变量记录循环次数,每次自增长1,打印变量,来计算长度
# l = [1,2,3,4,5]
# m = 0
# for j in l:
# m += 1
# print(m)

# # 函数体代码定义截断只检测语法 不执行代码
# def test():
# hdhfd
# sdafsd
# sdafjsldakj
# sdfljsda;lf;lskdf;l
#
# # print(test()) 上面单纯的定义函数没有错,不执行,只检测语法,里面都是变量,没有语法错误,但是一执行就会报错
"""
可以通过变量名找到变量对应的值
可以通过函数名+括号 找到函数体所对应的代码并执行
"""


# 函数名的命名规则跟变量名一模一样
# 1 数字字母下划线 2 不能以数字开头 3 不能与保留关键字重复 比如 print

# 函数就是工具,并且函数必须先定义后调用(函数名+括号)


# # 定义一个自己测量长度的函数
# def my_len(): # 定义一个函数,函数名为 my_len()
# n = 0 # 定义变量
# for i in s: # for循环取值
# n += 1 # 每取值循环一次,变量自增长1
# print(n) # 最后打印变量来计算循环次数,从而得到长度
# s = 'hello'
# my_len() # 一次定义,可以通过函数名多次调用 5

# 定义这个计算长度的函数,就是将for循环的代码放到某一个地方 谁要用谁就拿,定义函数,谁用谁调用





































































posted on 2019-07-08 21:12  xiaozhen·py  阅读(196)  评论(0)    收藏  举报