纯文本内容
各个字符的意义
w:write only
没有的文件会新建
已有的文件会覆盖原有文件内容
r:read only
没有的文件会出现报错
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/passwd1'
只能读一遍,因为文件指针的问题
print(f.tell()) # 查看文件指针的位置
才开始文件指针在最开始的位置,读一遍之后指针指到了文件末尾
所以再读一遍,无内容
a:write only
没有的文件会新建
已有的文件会在原有文件后追加内容
w+:read write
没有的文件会新建
原有文件内容清空
r+:read write
没有的文件会报错
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/passwd1'
文件指针指在那里,写的时候就写在那里
已有文件文件开头替换成python
a+:read write
没有的文件会新建
已有文件文末添加内容
实例
打开文件
f = open('/tmp/passwd','r+')
print(f) #生成一个对象
操作
# 读操作1
# content = f.read()
# print(content)
# 读操作2
# print(f.read())
# 写操作
# f.write('python')
# 查看文件读写权限
# print(f.readable())
# print(f.writable())
关闭文件
f.close() # 一定要关闭文件否则会一直占用系统资源
# 在写的时候可以先写打开文件和关闭文件,再写文件的操作内容
文件指针
文件才一打开的时候,文件指针在文件内容一开始的地方。当文件读取一遍的时候,文件指针随读取默认向下,直到文件末尾,所以此时再读取一遍时,无法读取到文件的内容
非纯文本内容
如果读取图片,音频或视频(非纯文本文件),需要通过二进制的方式来进行读取。
读取文本文件
r r+ w w+ a a+ == rt rt+ wt wt+ at at+
读取二进制文件
rb rb+ wb wb+ ab ab+
复制非纯文本内容
# 将old.png复制到new.png
f1 = open('old.png', 'rb')
print(f1)
# print(f1.read())
content = f1.read()
print(content) # 读取old.png中的内容
f2 = open('new.png', 'wb') # 新建一个new.png文件
f2.write(content) # 在new.png中写入old.png的内容
文件的常用操作
默认情况下读取文件的所有内容,小的文件,直接用read()读取即可
如果是一个大文件(文件大小>内存大小) readline()
读取
f = open('/tmp/passwd')
print(f.read(2)) # 按字符读取
# 类似于head -c
print(f.readline()) # 按行读取
print(f.readlines()) # 读取文件内容,返回一个列表,列表元素分别为文件的行内容
对于每一行,去掉后边的\n
# 方法一
print([line.strip('\n') for line in f.readlines()])
# 方法二
print(list(map(lambda x:x.strip('\n'),f.readlines())))
f.close()
写入
f = open('/tmp/passwd','w')
f.write('hello') # 从指针所在位置写入,写的就是字符串的内容
f.writelines(['a','b'])
print(f.writable())
f.close()
指针
f = open('/tmp/passwd','r')
print(f.tell())
print('1:',f.read(3))
print(f.tell())
f.seek(0,0)
print(f.tell())
f.close()
seek:移动指针
第一个参数:偏移量
第二个参数:
0:移动指针到文件开头
1:当前位置
2:移动指针到文件末尾
注意:当第二个参数为1或2时,要改成二进制格式。即在open时后边加上b。
文件练习一
题目要求:创建文件data.txt,文件共100000行,每行存放一个1~100之间的整数
import random
f = open('data.txt','w+')
for i in range(100000):
f.write(str(random.randint(1,100)) + '\n')
# f.write('\n')
f.seek(0,0)
# print(f.tell())
print(f.read())
f.close()
文件练习二
题目要求:生成100个MAC地址并写入文件中,MAC地址前6位(16进制)为01-AF-3B
方法一(生成了100个MAC地址):
import random
import string
hex_num = string.hexdigits
for i in range(100):
n = random.sample(hex_num.upper(), 6) # 随机选择出2个
# print(n)
print('01-AF-3B' + '-' + n[0] + n[1] + '-' + n[2] + n[3] + '-' + n[4] + n[5])
方法二:
import random
import string
def creat_mac():
MAC = '01-AF-3B'
hex_num = string.hexdigits
for i in range(3):
n = random.sample(hex_num, 2)
sn = '-' + ''.join(n).upper() # 用空将列表n中的值拼接在一起,
# 并通过upper将所有的字母都变成大写
MAC += sn
return MAC
def main():
with open('mac.txt', 'w') as f:
for i in range(100):
mac = creat_mac()
print(mac)
f.write(mac + '\n')
main()
文件练习三
题目要求:京东二面编程题
1.生成一个大文件ips.txt,要求1200行,每行随机为172.25.254.0/24段的ip;
2.读取ips.txt文件统计这个文件中ip出现频率排前10的ip;
# 生成1200个ip
# 方法一:
import random
def create_ips():
with open('ips.txt', 'w') as f:
ip = '172.25.254.'
for i in range(1200):
f.write(ip + str(random.randint(0, 254)) + '/24' + '\n')
# create_ips()
# 方法二:
import random
def create_ips(filename):
ips = ['172.25.254.' + str(i) for i in range(0, 255)]
# print(ips)
with open(filename, 'a+') as f:
f.write(random.sample(ips, 1)[0] + '\n')
create_ips('ips.txt')
# 排序
def sorted_ip(filename, count=10):
ips_dict = dict()
with open(filename) as f:
for ip in f:
if ip in ips_dict:
ips_dict[ip] += 1
else:
ips_dict[ip] = 1
sorted_ips = sorted(ips_dict.items(), key=lambda x: x[1], reverse=True)[:10]
return sorted_ips
print(sorted_ip('ips.txt'))
用with省去close
用with来省去每一次都要close的麻烦。
例如:将passwd中的文件内容复制到passwdbackup之中。
方法一:python2和python3中共同的用法。(python2中只能这样用)
with open('/tmp/passwd', 'r') as f1:
content = f1.read()
with open('/tmp/passwdbackup', 'w+') as f2:
f2.write(content)
方法二:python3中的另一种用法。
with open('/tmp/passwd', 'r') as f1, \
open('/tmp/passwdbackup', 'w+') as f2:
f2.write(f1.read())
f2.seek(0, 0)
f2.read()
在此我们引用装饰器一节中的计时器,来对两种方法进行装饰。完整内容如下:
# 装饰器——记时器
# 加装饰器查看两种方式哪一个所用时间更短
import time
def timeit(func):
def get_time(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print('运行时间为%.6f' % (end_time - start_time))
return get_time
# python3和python2中都能这样写
# python2中只能这样写
@timeit
def f1():
with open('/tmp/passwd', 'r') as f1:
content = f1.read()
with open('/tmp/passwdbackup', 'w+') as f2:
f2.write(content)
# python3中还可以这样写
@timeit
def f2():
with open('/tmp/passwd', 'r') as f1, \
open('/tmp/passwdbackup', 'w+') as f2:
f2.write(f1.read())
# f2.seek(0, 0)
# f2.read()
f1()
f2()
所得结果如图:
结论:我们发现f2方法所用时间更短。
文件与生成器结合
# 制作一个生成器
def bylineread(filename):
with open(filename) as f:
line = f.readline()
while line:
yield line # 说明是一个生成器
line = f.readline()
# read是一个生成器对象
read = bylineread('data.txt')
print(read)
# 读取生成器内容
方法一:next读取
print(next(read))
print(next(read))
方法二:for循环
for item in read:
print(item)
方法三:Iterable(可迭代对象)
from collections import Iterable
f= open('data.txt')
print(isinstance(f,Iterable))
for i,item in enumerate(f):
if i == 5: # 可以控制想要读取内容的多少
break
print(i,item)