一、文件对象的用法汇总
说明:假定file是通过open的全局函数获取的文件对象!
file.close()
"""特点:关闭文件,关闭后文件不能再进行读写操作"""
file.flush()
"""特点:刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入"""
file.fileno() #了解
"""返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上"""
file.isatty() #了解
如果文件连接到一个终端设备返回 True,否则返回 False。
file.next()
"""返回文件下一行"""
file.read([size])
"""从文件读取指定的字节数,如果未给定或为负则读取所有"""
file.readline([size]) #掌握!
"""读取整行,包括 "\n" 字符"""
file.readlines([sizeint]) #列表!
"""读取所有行并返回列表,若给定sizeint>0,则是设置一次读多少字节,这是为了减轻读取压力"""
file.seek(offset[, whence])
"""设置文件指针的位置"""
file.tell()
"""返回文件当前位置"""
file.truncate([size])
截取文件,截取的字节通过size指定,默认为当前文件位置。
file.write(str)
将字符串写入文件,返回的是写入的字符长度。
file.writelines(sequence)
"""向文件写入一个序列字符串列表,如果“需要换行“则要自己加入每行的换行符"""
二、文件行读取
需求:按行读取-->readline
file = open('passwd', 'r') #说明mode可以省略(位置参数)!
while True:
# 说明:每次读取一行-->默认带有一个换行的符号"\n",所以下面打印的适合不换行
line = file.readline() # type -->str
# 说明:如果没有读取数据(读到文件的结尾,返回为空,即None),则跳出循环!
if not line:
break
print(line, end='')
file.close()
原因1:由于read()默认是一次性读进内存,如果文件比较大,文件大小>=内存的大小,就会报错!
原因2:通长文本文件的每一行都有自己的意义,可以对每一行进行相同的书写格式便于处理!
readlines()特点:和read()方法一样都是一次性读取文件,但是不同之处是她将每一行的内容保存到列表中!
file = open('passwd', mode='r')
list1 = file.readlines()
print(type(list1)) # type-->list
# 每一行的内容:'root:x:0:0:root:/root:/bin/bash\n'
for i in list1:
print(i, end='')
file.close()
备注:只有文本文件才有行的概念,二进制没有,主要是为了提高读写的效率!
需求1:读取内容,并返回一个列表,去掉后面的\n
file = open('passwd', mode='r')
# 方式1:这里使用列表生成式
#list1 = [line.strip() for line in file.readlines()]
# 方式2:匿名函数-->map处理
list2 = list(map(lambda x: x.strip(), file.readlines()))
print(list2) # type-->list
# 注意:两个之中必须注释一个(因为:文件指针的原因,否则读取不到任何内容)
小知识点:文件对象本身就可迭代对象(文件迭代器),像一个序列一样,所以可以通过for循环来遍历文件的内容
print([line.strip() for line in open('passwd', mode='r')])
思考:如果对文件对象进行操作之后,总是忘记关闭资源,如何处理?
上下文管理器管理资源:需要把打开的文件放在with语句中,这样with语句就会帮我们自动关闭文件!
with open('passwd','r') as file:
file.read()
# 判断文件对象是否关闭
print('文件是否关闭:',file.closed) #True(关闭了)
三、写文件
文件指针:标明文件读写的位置!
文件对象提供了两种方法来操作文件指针:
#file.seek(offset[, whence])
说明: [, whence]是非必须参数,默认是0表示当前位置!
"""whence --> 0(表示从文件的开头开始计算);1(表示指针从当前位置开始计算);2(表示从文件末尾开始计算)"""
offset --> 文件的偏移量;-3(某个位置向左偏移3处-->只有b);0(某个位置);3(某个位置向右偏移-->只有b)
说明:偏移量是字节还是字符取决于模式!
练习1:
file=open('passwd','r') #说明:报错的原因是没有使用b的模式-->按照字节而不是字符
# 打开文件后,看文件指针的位置
print(file.tell())
# 由于是文本形式的读取,所以是字符的形式-->默认从当前位置!
print(file.read(5))
# 此时的指针
print(file.tell())
# 移动文件指针,读取文件末尾的8个字符
file.seek(-10,2)
print(file.tell())
print(type(file.read()))
原因:在文本文件中没有使用b模式选项打开的文件,只允许从文件头开始计算相对位置,从文件尾计算时就会引发异常!
文件对象提供的写文件方法
"""write(str或者byres):输出字符串或者字节串;只有二进制模式(b)打开的文件才能写入字符串!"""
"""writelines(可迭代的对象):输出多个字符串或者字节串!"""
os.lineseq -->系统的换行符!
需求2:创建文件data.xtx,文件共10000行,每行存放一个1~100之间的整数
# (1)产生1~100之间的整数
import random
# (2)创建文件-->open的w模式,有则覆盖内容,没有则创建(涉及文件的写)
file=open('data.txt','w') #或者a+ 结合移动文件指针!
for i in range(1000):
file.write(str(random.randint(1,100)) +'\n')
file.close()
需求3:
# 需求:将一个文件的内容写到第二个文件中-->复制!
with open('passwd','r') as file1,open('passwd1','w') as file2:
file2.write(file1.read())
# 注意:file1和file2是全局变量!
# w模式在字节对象尚未关闭之前,每次也是追加(只有open之后文件存在会覆盖)!
# 注意:新建文件的用户身份等!
# w模式是open之后直接追加!
print(file1.closed,file2.closed)
细节:python2和python3的区别!
需求4:
"""
生成100个MAC地址并写入文件中,MAC地址前6位(16进制)为01-AF-3B
格式如下:01-AF-3B-xx-xx-xx
"""
import random
import string
# 生成16进制的数的字符串(序列)[A-Za-z0-9]组成!
hex_num=string.hexdigits
# (1)定义一个函数产生需要的MAC地址
def create_mac():
MAC='01-AF-3B'
# 拼接-->每次随即选出两个字符
for i in range(3):
# 对比与choice的区别和联系!
# sample随机选择的不重复;choice随机选取的可以重复!
# 注意:sample获取的是列表,每一个元素是一个字符!
n=random.sample(hex_num,2)
#MAC地址是大写-->所以需要大小写转换(细节问题)
# 执行逻辑:.join(n)先拼接成字符串 -->''+再拼接字符串-->upper()大小写转换!
sn ='-' +''.join(n).upper()
# sn就是-XX形式!
MAC += sn
return MAC
# (2)主函数:批量生成100个MAC地址,每生成一个就写入到文件中!
def main():
# 以写的方式打开一个文件
with open('mac.txt','w') as f:
for i in range(100):
mac=create_mac()
print(mac)
# w模式下,不关闭文件对象时,覆盖原文件之后是追加!(换行)
f.write(mac+'\n')
#调用主函数
main()
需求5:
"""
京东二面编程题
# 1. 生成一个大文件ips.txt,要求1200行,每行随机为172.25.254.0/24段的ip;
# 2. 读取ips.txt文件统计这个文件中ip出现频率排前10的ip;
"""
细节:如果题目改成此网段有效的IP--->主机位全0代表网络和全1代表广播地址!
# (1)产生ip文件内容-->模拟操作!
def create_ip_file(filename):
"""
:param filename:文件名字
:return: 返回的是ip
"""
ips = ['172.25.254.' + str(i) for i in range(0, 255)]
# 测试:print(ips)
with open(filename, 'a+') as f:
# 生成1200个ip
for i in range(0, 1200):
# 说明:等价-->seek
f.write(random.sample(ips, 1)[0] + '\n')
# 调用函数-->测试生成文件,实际可能已经给出文件!
create_ip_file('ips.txt')
# (2)排序!
def sorted_ip(filename, count=10):
# 工厂函数产生字典
ips_dict = dict()
# 文件对象也是一个可迭代的对象
with open(filename) as f:
for ip in f:
# 细化:去除文件末尾的空格(\n),可以去掉这行!
ip =ip.strip()
# 判断每一行的内容是不是在里面-->键找值(套路)!
if ip in ips_dict:
ips_dict[ip] += 1
else:
ips_dict[ip] = 1
# 排序-->默认是升序!
# ips_dict.items()-->是一个列表(列表的每一个元素是元组-->ip:count)!
sorted_ip = sorted(ips_dict.items(), key=lambda x: x[1], reverse=True)[:count]
# 返回的还是一个列表(列表是截取的是前出现频率最高的前10个ip)!
return sorted_ip
# 调用函数
print(sorted_ip('ips.txt'))