07 文件操作

1 文件操作

1.1 前提条件

  • 文件路径:
    • 绝对路径
    • 相对路径
  • 编码方式:
    • utf-8
    • gbk
  • 打开方式:
    • 只读
    • 只写
    • 追加
    • 读写
    • 写读

1.2 操作步骤

  • 打开
# 绝对路径
# 什么编码方式存的文件,就以什么编码方式打开
f = open('d:/test.txt', mode='r', encoding='utf-8')
  • 操作
s = f.read()
print(s)
  • 关闭
f.close()

1.3 只读

  • open的mode:
    • r:读出来的是字符串
    • rb:读出来的是二进制

1.4 只写

  • w的注意事项:

    • 没有此文件就会创建文件写
    • 有文件清除文件再写
  • open的mode:

    • w

      • f = open('./ddd.log', mode='w', encoding='utf-8')
        f.write('木头、斧头')
        f.close()
        
    • wb

      • f = open('./ddd.log', mode='wb')
        f.write('罐头、大头、小头'.encode("gbk"))
        f.close()
        

1.5 追加

在文件末尾追加内容

  • open的mode:

    • a

      • f = open('./相对路径.txt', mode='a', encoding="utf-8")
        f.write('罐头')
        f.close()
        
  • ab

    • f = open('./相对路径.txt', mode='ab')
      f.write('木头'.encode('utf-8'))
      f.close()
      

1.6 组合操作

1.6.1 r+ 和 r+b模式

  • 先读后写:

    • 只会读写之前的内容

    • 后面写的内容始终不会读

    • f = open('./ddd.log', mode='r+', encoding="utf-8")
      s = f.read()
      print(s)
      f.write('罐头')
      f.close()
      
  • 先写后读

    • 先从头开始写,写多少占多少位,是二进制的位数

    • 只会读还没有占位的剩余的部分

    • 如果占位不小心占了汉字的字节,后面读的会出现错误

    • f = open('./ddd.log', mode='r+', encoding="utf-8")
      f.write('先写')
      s = f.read()
      print(s)
      f.close()
      
      
    • # 移动光标插入
      f = open('./ddd.log', mode='r+', encoding="utf-8")
      f.seek(6)
      f.write('插入')
      s = f.read()
      print(s)
      f.close()
      
  • r+b也是读写,只是写的是bytes类型

1.6.2 w+ 和 w+b 模式

只要是w,都是先清除后再写。

该模式不太常用

f.seck(0) 调节光标

1.6.3 a+ 和 a+b 模式

write始终是追加在最后

但是多一个读的动作,可以将光标移到指定位置去读

f = open('./ddd.log', mode='a+', encoding="utf-8")
f.seek(0)
f.write('读读')
s = f.read()
print(s)
f.close()

2 功能

2.1 read 读

  • 可以设置多少个字符(能看到的文字的最小单位)
# ddd.log 的内容:
# aa啊啊拜托啊啊
# 读出来:aa啊
f = open('./ddd.log', mode='r+', encoding="utf-8")
s = f.read(3)
print(s)
f.close()

2.2 seek 定光标

  • 可以设置多少个字节
# ddd.log 的内容:
# aa啊啊拜托啊啊
# 读出来:a啊啊拜托啊啊
f = open('./ddd.log', mode='r+', encoding="utf-8")
f.seek(1)
s = f.read()
print(s)
f.close()

2.3 tell 获取光标位置

  • 光标的位置时刻根据对文件的操作在变化
f = open('./ddd.log', mode='r+', encoding="utf-8")
f.seek(1)
print(f.tell())
s = f.read()
print(s)
print(f.tell())
f.close()
  • 利用光标现在的位置,将后三个字读出来
f = open('./ddd.log', mode='a+', encoding="utf-8")
f.write('追加')
count = f.tell()
f.seek(count - 3 * 3)
s = f.read()
print(s)
f.close()

2.4 readline 和 readlines

  • readline一行一行读
  • readline有换行符
  • readlines返回所有行,返回对象是list
f = open('d:/test.txt', mode='r+', encoding="utf-8")
line1 = f.readline()
print(line1)
line2 = f.readline()
print(line2)
# 输出list 
lines = f.readlines()
print(lines)
f.close()

输出结果如下:

订立当当。葫芦娃abccccc

【接入计费出账】

['计划于10月28日进行\n', '影响:\n', '支持接入\n', '上线的时候\n', '计划上线。\n']

2.4 其他功能

  • flush 强制保存
  • readable 是否可读
  • readline 一行一行读
  • trancate 对源文件进行截取

3 其他技巧

(1) 使用with:

  • 打开多个文件,
  • 省掉一个close语句
  • 如下所示:
with open('d:/test.txt', mode='r+', encoding="utf-8") as f1,\
        open('./ddd.log', mode='r+', encoding="utf-8") as f2:
    print(f1.readlines())
    print('.................................')
    print(f2.readlines())

输入结果如下:

['订立当当。葫芦娃abccccc\n', '【Billing支持CFS接入计费出账】\n', '计划于10月28日进行Billing模块升级上线\n', '变更影响:\n', '支持CFS接入计费,后台模块,预计对客户无感,计费流延迟5分钟内\n', '上线的时候,bp-usage会有port报警,相关告警请忽略\n', '计划上线开始时间:2019年10月28日18:00,预计结束时间19:00。\n']
.................................
['aa啊啊插入啊啊追加\n', 'eeeee\n', 'ddfdd']

(2) 删除和重命名文件:

import os
os.remove(filename)
os.rename(oldfilename, newfilename)

4 小练习

先注册,将注册的用户名和密码写入文件。注册完成后在登录,登录从文件中读出来校验,给三次机会。

#-*- coding:utf-8 -*-
__author__ = 'xiao33x'

import getpass

# 根据用户名和密码判断用户是否存在
def getUser(uname=None, upwd=None):
    with open('注册.txt',mode='a+', encoding="utf-8")  as f:
        f.seek(0)
        while 1:
            # 依据大小来获取每次读取的行数,在IO和内存寻找平衡点
            lines = f.readlines(10)
            # print(lines)
            if not lines:
                break
            for line in lines:
                # 记得要把‘\n’给去掉
                line = line.replace('\n','')
                fname, fpwd = line.split('=')
                print('fname:', fname, ';  fpwd:', fpwd)
                if upwd != None and uname == fname and upwd == fpwd:
                    return True
                elif upwd == None and uname == fname:
                    return True
    return False


# 添加用户
def addUser(uname=None, upwd=None):
    with open('注册.txt',mode='a+', encoding="utf-8")  as f:
        # 因为a+会直接把光标放在最后,所以先加光标放在前面来
        f.seek(0)
        while 1:
            # 依据大小来获取每次读取的行数,在IO和内存寻找平衡点
            lines = f.readlines()
            # print(lines)
            if not lines:
                break
            for line in lines:
                fname, fpwd = line.split('=')
                # print('fname:', fname, ';  fpwd:', fpwd)
                if uname == fname:
                    print('用户已存在')
                    return False
        f.write('{name}={pwd}\n'.format(name=uname, pwd=upwd))
    print('注册成功')
    return True


if __name__ == '__main__':
    fileStr = '{name}={pwd}'
    while 1:

        print('''\
        1. 注册:
        2. 登录:
        3. 退出''')
        op = input('请选择你的操作:')
        if op == '3':
            print('已结束!')
            break
        if op ==  '1':
            name = input('用户名:')
            pwd = ''
            cpwd = ''
            while 1:
                pwd = getpass.getpass('密码:')
                cpwd = getpass.getpass('确认密码:')
                if pwd == cpwd and pwd != '':
                    break
                else:
                    print('两次密码输入不一致!')
            addUser(name, pwd)
        if op == '2':
            name = input('用户名:')
            pwd = getpass.getpass('密码:')
            existUser = getUser(name, pwd)
            if existUser:
                print('登录成功!')
            else:
                print('登录失败!')


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容