【Python基础】文件操作

文件操作

计算机系统分为:计算机硬件,操作系统,应用程序三部分。

  我们用Python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作

硬件,众所周知,应用程序是无法直接操作硬件的,这就用到了操作系统。操作系统把复杂的硬件操作封装成简单的接口给用

户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的

数据永久保存下来。有了文件的概念,我们无需再去考虑操作硬盘的细节,只需要关注操作文件的流程:

#1. 打开文件,得到文件句柄并赋值给一个变量

#2. 通过句柄对文件进行操作

#3. 关闭文件

文件 读 r 操作

f=open('陈粒',encoding='utf-8')
data=f.read()
print(data)
f.close()

f=open('xxx')
data=f.read()
print(data)


f=open('陈粒','r',encoding='utf-8')
data=f.read()
# print(data)
print(f.readable())
print('第1行',f.readline(),end='')
print('第2行',f.readline())
print('第3行',f.readline())
# for i in range(1):
#     pass
print('第4行',f.readline())
print('第5行',f.readline())
print('第6行',f.readline())
print('第7行',f.readline())

data=f.readlines()
print(data)
f.close()
读文件

文件 写 w 操作

f=open('陈粒1','w',encoding='utf8')
# f.read()
f.write('11111111
')
f.write('222222222
')
f.write('333
4444
555
')
# f.writable()
f.writelines(['555
','6666
'])
f.writelines(['555
','6666
',1]) # 文件内容只能是字符串,只能写字符串
f.close()
写文件

文件 追加 a 操作

f=open('陈粒1','a',encoding='utf-8')
f.write('追加方式写到文件最后')
追加写操作

"+" 表示可以同时读写某个文件

r+, 读写【可读,可写】

w+,写读【可读,可写】

a+, 写读【可读,可写】

文件修改

src_f=open('xxx','r',encoding='gbk')
data=src_f.readlines()
src_f.close()

# for i in data:
#     print(i)
print(data)
dst_f=open('xxx','w',encoding='gbk')
# dst_f.writelines(data)
dst_f.write(data[0])
dst_f.close()

with open('a.txt','w') as f:
    f.write('1111
')


src_f=open('xxx','r',encoding='gbk')
dst_f=open('xxx','w',encoding='gbk')
修改文件

推荐-以 with 方式打开多个文件

with open('xxx','r',encoding='gbk') as src_f,
        open('xxx_new','w',encoding='gbk') as dst_f:
    data=src_f.read()
    dst_f.write(data)

f=open('a.txt')
print(f.encoding) #查看文件编码
View Code
with open('a.txt','r',encoding='utf8') as fa:
    for row in fa:      #fa获得多行数据组成的列表
    print(row.strip())

以 bytes(二进制)方式打开文件(主要是视频、音频文件)

f=open('test11.py','rb',encoding='utf-8')     #b的方式不能指定编码
f=open('test11.py','rb') #b的方式不能指定编码
data=f.read()

#'字符串'---------encode---------》bytes
#bytes---------decode---------》'字符串'

print(data)
print(data.decode('utf-8'))
f.close()


f=open('test22.py','wb') #b的方式不能指定编码
f.write(bytes('1111
',encoding='utf-8'))
f.write('中国'.encode('utf-8'))

f=open('test22.py','ab') #b的方式不能指定编码
f.write('中国'.encode('utf-8'))

open('a.ltxt','wt')
View Code

补充:需求:读取几万行日志文件的最后一行
f.readlines() 直接全部读出来放在内存中 很耗内存空间

# f=open('日志文件','rb')
# data=f.readlines()
# print(data[-1].decode('utf-8'))

f=open('日志文件','rb')

# for i in f.readlines():
#     print(i)

#循环文件的推荐方式,以行为单位读取,取一行用一行 不全部放在内存中
# for i in f:
#     print(i)

for i in f:
    offs=-10
    while True:
        f.seek(offs,2)
        data=f.readlines()
        if len(data) > 1:
            print('文件的最后一行是%s' %(data[-1].decode('utf-8')))
            break
        offs*=2
View Code

 ###操作文件的一些方法总结

#掌握
f.read() #读取所有内容,光标移动到文件末尾
f.readline() #读取一行内容,光标移动到第二行首部
f.readlines() #读取每一行内容,存放于列表中

f.write('1111
222
') #针对文本模式的写,需要自己写换行符
f.write('1111
222
'.encode('utf-8')) #针对b模式的写,需要自己写换行符
f.writelines(['333
','444
']) #文件模式
f.writelines([bytes('333
',encoding='utf-8'),'444
'.encode('utf-8')]) #b模式

#了解
f.readable() #文件是否可读
f.writable() #文件是否可读
f.closed #文件是否关闭
f.encoding #如果文件打开模式为b,则没有该属性
f.flush() #立刻将文件内容从内存刷到硬盘
f.name

"""
练习,利用b模式,编写一个cp工具,要求如下:
  1. 既可以拷贝文本又可以拷贝视频,图片等文件
  2. 用户一旦参数错误,打印命令的正确使用方法,如usage: cp source_file target_file
  提示:可以用import sys,然后用sys.argv获取脚本后面跟的参数
使用cmd命令行执行test1.py 后面可以跟上参数,用sys.argv获取参数列表[test1.py,arg1,arg2...]
"""

import sys
if len(sys.argv) != 3:
    print('usage: cp source_file target_file')
    sys.exit()

print(sys.argv)     #['test1.py', 'aa.txt', 'bb']
source_file,target_file=sys.argv[1],sys.argv[2]
with open(source_file,'rb') as read_f,open(target_file,'wb') as write_f:
    for line in read_f:
        write_f.write(line)

文件内光标移动

一: read(3):

  1. 文件打开方式为文本模式时,代表读取3个字符

  2. 文件打开方式为b模式时,代表读取3个字节

二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate

注意:

  1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

  2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果

文件的修改

文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:

方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

import os

with open('./a.txt','r') as read_f,open('./newa.txt','w') as write_f:
    data=read_f.read() #全部读入内存,如果文件很大,会很卡
    data=data.replace('alex','SB') #在内存中完成修改

    write_f.write(data) #一次性写入新文件

os.remove('./a.txt')
os.rename('./newa.txt','a.txt')

方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件

import os

with open('./a.txt') as read_f,open('./newa.txt','w') as write_f:
    for line in read_f:
        line=line.replace('alex','SB')
        write_f.write(line)

os.remove('./a.txt')
os.rename('./a.txt','./a.txt') 

案例:在文件中查询内容

"""实现在文件中 查询某一行打印出这行下级的内容"""
def fetch(data):
    backend_data = "backend %s"%data
    with open('haproxy.conf','r') as read_f:
        tag = False
        res = []
        for read_line in read_f:
            if read_line.strip() == backend_data:
                tag = True
                continue
            if tag and read_line.startswith("backend"):
                break
            if tag and read_line.strip() is not None:
                print(read_line.strip())
                res.append(read_line.strip())
    return res

def add():
    pass

def change():
    pass

def delete():
    pass

if __name__ == '__main__':
    msg = '''
        1:查询
        2:添加
        3:修改
        4:删除
        5:退出
    '''
    msg_dic = {
        '1': fetch,
        '2': add,
        '3': change,
        '4': delete,
    }
    while True:
        print(msg)
        choice = input("输入你的选项>>>").strip()
        if not choice:continue
        if choice =="5":break
        data = input("输入你的数据>>>").strip()
        res = msg_dic[choice](data) #res 是所选择函数的返回值
        print(res)

补充知识:多层while循环嵌套时 如何跳出?

"""输入一个quit_all 退出所有while层的循环"""
tag=True
while tag:
    print('leve1')
    choice=input("level1>>: ").strip()
    if choice == 'quit':break
    if choice == 'quit_all': tag = False
    while tag:
        print('level2')
        choice = input("level2>>: ").strip()
        if choice == 'quit': break
        if choice == 'quit_all': tag = False
        while tag:
            print('level3')
            choice = input("level3>: ").strip()
            if choice == 'quit': break
            if choice == 'quit_all': tag = False

文件/文件夹操作参考 os模块

# import os
# # os.rename('a.txt','a.txt.bak')
# os.rename('b.txt','aa.py')     #rename 修改文件或文件夹名称(或类型)

参考:http://www.cnblogs.com/linhaifeng/articles/5984922.html#_label28

原文地址:https://www.cnblogs.com/XJT2018/p/10854939.html