Python 第九章 文件操作

1.使用os.path操作目录

import os
import time

# 获取绝对路径
print(os.path.abspath("abc.txt")) # G:\publish\codes\12\12.2\abc.txt
# 获取共同前缀
print(os.path.commonprefix(['/usr/lib', '/usr/local/lib'])) # /usr/l
# 获取共同路径
print(os.path.commonpath(['/usr/lib', '/usr/local/lib'])) # \usr
# 获取目录
print(os.path.dirname('abc/xyz/README.txt')) #abc/xyz
# 判断指定目录是否存在 
print(os.path.exists('abc/xyz/README.txt')) # False
# 获取最近一次访问时间
print(time.ctime(os.path.getatime('os.path_test.py')))
# 获取最后一次修改时间
print(time.ctime(os.path.getmtime('os.path_test.py')))
# 获取创建时间
print(time.ctime(os.path.getctime('os.path_test.py')))
# 获取文件大小
print(os.path.getsize('os.path_test.py'))
# 判断是否为文件
print(os.path.isfile('os.path_test.py')) # True
# 判断是否为目录
print(os.path.isdir('os.path_test.py')) # False
# 判断是否为同一个文件
print(os.path.samefile('os.path_test.py', './os.path_test.py')) # True

2.打开文件

open()函数默认打开文件的模式是r,只读。

在使用open函数时,如果其第三个参数是0或False,那么该函数打开的文件就是不带缓冲的,是1或True就带,就有更好的性能。如果是大于1的整数,就是知道缓冲区大小,是负数就代表默认的缓冲区大小。

打开文件之后就可调用文件对象的属性和方法了。文件对象支持如下常见的属性:

  • file.closed:该属性返回文件是否已经关闭
  • file.mode:该属性返回被打开文件的访问模式
  • file.name:返回文件的名称
# 以默认方式打开文件
f = open('open_test.py')
# 访问文件的编码方式
print(f.encoding) # cp936
# 访问文件的访问模式
print(f.mode) # r
# 访问文件是否已经关闭
print(f.closed) # False
# 访问文件对象打开的文件名
print(f.name) # open_test.py

文件打开模式

  • r:只读模式。
  • w:写模式。
  • a:追加模式。
  • +:读写模式,可与其他模式结合使用。比如r+,w+都是读写模式。
  • b:二进制模式,可与其他模式结合使用。

w代表写模式,w+代表读写模式,但实际上他们差别不大,当这两种模式打开指定文件时,open函数都会立即清空文件内容,实际上都无法读取文件内容。

3.读取文件

3.1按字节或字符读取

文件对象提供read函数来按字节或字符读取文件内容,如果使用了b模式就按字节读,可以传入一个整数作为参数,用于指定最多读取多少个字节或字符。

f = open('基础.py','r',True,encoding='utf-8')
while True:
    # 每次读取一个字符
    ch = f.read(1)
    # 如果没有读到数据就跳出循环
    if not ch:break
    print(ch,end='')
f.close()

上面程序采用循环一次读取每一个字符,每读到一个字符,程序就输出该字符。

如果在调用read函数时不传入参数,默认读取全部文件内容。

如果要读取的文件所使用的字符集和当前操作系统的字符集不匹配,有两种解决方法:

  • 使用二进制模式读取,然后用bytes的decode()方法恢复成字符串。
  • 利用open函数的encoding参数指定字符集。
# 指定使用二进制方式读取文件内容
f = open("read_test3.py", 'rb', True) # rb模式采用二进制读
# 直接读取全部文件,并调用bytes对象的decode将字节内容恢复成字符串
print(f.read().decode('utf-8'))
f.close()
3.2按行读取

如果程序要读取行,通常只能用文本方式来读取,只有文本文件才有行的概念,二进制文件没有。

  • readline([n]):读取一行内容,如果指定n,就只能读取此行内的n个字符。
  • readlines():一下子读取文件所有行。
3.3使用fileinput读取多个输入流

fileinput模块可以把多个输入流合并在一起。

  • fileinput.input(files=None,inplace=False,backup='',bufsize=0,mode='r',openhook=None):files参数用于指定多个文件输入流。该函数返回一个Fileinput对象。
  • fileinput.filename():返回文件名
  • fileinput.fileno():返回当前文件的文件描述符。
  • fileinput.lineno():当前读取的行号。
  • 等等

这个模块不能指定字符集。

import fileinput
# 一次读取多个文件
for line in fileinput.input(files=('info.txt', 'test.txt')):
    # 输出文件名,当前行在当前文件中的行号
    print(fileinput.filename(), fileinput.filelineno(), line, end='')
# 关闭文件流
fileinput.close()
3.4文件迭代器

文件对象本身就是可遍历的,所以可以用for in循环来遍历文件内容

# 指定使用utf-8字符集读取文件内容
f = open("for_file.py", 'r', True, 'utf-8')
# 使用for-in循环遍历文件对象
for line in f:
    print(line, end='')
f.close()
# 将文件对象转换为list列表
print(list(open("for_file.py", 'r', True, 'utf-8')))

此外,sys.stdin也是一个类文件对象,因此程序可以用for in循环遍历,这意味着程序可以通过forin循环获取用户的键盘输入。

import sys
# 使用for-in循环遍历标准输入
for line in sys.stdin:
    print('用户输入:', line, end='')

获取用户键盘输入,用户每输入一行就会显示这一行。

3.5管道输入
3.6使用with语句

可以自动关闭文件

# 使用with语句打开文件,该语句会负责关闭文件
with open("readlines_test.py", 'r', True, 'utf-8') as f:
    for line in f:
        print(line, end='')
3.7使用linecache随机读取指定行

随机读取使用了utf-8字符集的指定行

import linecache
import random

# 读取random模块的源文件的第3行
print(linecache.getline(random.__file__, 3))
# 读取本程序的第3行
print(linecache.getline('linecache_test.py', 3))
# 读取普通文件的第2行
print(linecache.getline('utf_text.txt', 2))

4.写文件

如果以r+、w、w+、a、a+模式打开文件,则都可以写入。当以r+、w、w+打开文件时,文件指针位于文件开头处;当以a、a+模式打开文件时,文件指针位于文件结尾。当以w、w+打开文件时,程序会立即清空文件的内容。

4.1文件指针:

用于标明文件读写的位置。

文件对象提供以下方法操作文件指针:

seek(offset[,whence]):该方法把文件指针移动到指定位置。当whence为0时(这是默认值),表面从文件开头开始计算,比如将offset设为3,就是将文件指针移动到第3处;当whence为1时,表明从指针当前位置开始计算,比如文件指针当前在第5处,将offset设为3,就是将文件指针移动到第8处;当whence为2时,表面从文件结尾开始计算,比如将offset设为-3,表面将指针移动到文件结尾倒数第3处。

tell():判断文件指针的位置。

当程序使用文件对象读写数据时,文件指针会自动向后移动:读写了多少个数据,就向后移动多少个位置。

f = open('filept_test.py', 'rb')
# 判断文件指针的位置
print(f.tell()) # 0
# 将文件指针移动到3处
f.seek(3)
print(f.tell()) # 3
# 读取一个字节,文件指针自动后移1个数据
print(f.read(1)) # o
print(f.tell())  # 4
# 将文件指针移动到5处
f.seek(5)
print(f.tell())  # 5
# 将文件指针向后移动5个数据
f.seek(5, 1)
print(f.tell())  # 10
# 将文件指针移动到倒数第10处
f.seek(-10, 2)
print(f.tell())
print(f.read(1))  # d
4.2输出内容

文件对象提供的写文件的方法主要有两个:

  • write(str或bytes):输出单个字符串或字节串。只有以二进制
  • writelines(可迭代对象):输出多个字符串或多个字节串
import os
f = open('x.txt', 'w+')
# os.linesep代表当前操作系统上的换行符
f.write('我爱Python' + os.linesep)
f.writelines(('土门壁甚坚,'+ os.linesep,
    '杏园度亦难。'+ os.linesep,
    '势异邺城下,'+ os.linesep,
    '纵死时犹宽。'+ os.linesep))

当采用上面方法输出文件时,程序会使用当前操作系统默认的字符集。如果需要使用指定的字符集来输出文件,则可以用二进制形式----程序先将所输出的字符串转换成指定字符集对应的二进制数据(字节串),然后输出二进制数据。

import os
f = open('y.txt', 'wb+')
# os.linesep代表当前操作系统上的换行符
f.write(('我爱Python' + os.linesep).encode('utf-8'))
f.writelines((('土门壁甚坚,'+ os.linesep).encode('utf-8'),
    ('杏园度亦难。'+ os.linesep).encode('utf-8'),
    ('势异邺城下,'+ os.linesep).encode('utf-8'),
    ('纵死时犹宽。'+ os.linesep).encode('utf-8')))

以wb+模式打开文件,程序会以二进制形式输出文件,此时程序输出的必须是字节串,不能是字符串。因此程序调用encode方法将字符串转换成字节串,转换时指定使用utf-8字符集。

以w+、wb+模式打开文件会导致文件内容被清空,因此无论程序运行多少次,其输出的文件内容都只保留最近一次的输出数据。要想继续写要使用追加模式:

import os
f = open('z.txt', 'a+')
# os.linesep代表当前操作系统上的换行符
f.write('我爱Python' + os.linesep)
f.writelines(('土门壁甚坚,'+ os.linesep,
    '杏园度亦难。'+ os.linesep,
    '势异邺城下,'+ os.linesep,
    '纵死时犹宽。'+ os.linesep))

5.os模块的文件和目录函数

5.1与目录相关的函数
5.2与权限相关的函数
5.3与文件访问相关的函数
posted @ 2021-03-24 21:35  KKKyrie  阅读(82)  评论(0编辑  收藏  举报