在实际开发中我们需要对文件做一些操作,例如读写文件、在文件中新添内容等,通常情况下,我们会使用open函数进行相关文件的操作,下面将介绍一下关于open读写的相关内容。
open方法打开文件并返回一个文件对象,之后对文件的处理均需要基于返回的文件对象,如果文件不存在或者无法打开,则抛出OSError,详细方法如下:
open(file, mode='r', buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
file
: 需要打开的文件或者文件描述符,通常直接时文件即可
mode
:对于文件需要操作的模式,常用的如下:
字符
含意
'r'
读取(默认)
'w'
写入,并先截断文件
'x'
排它性创建,如果文件已存在则失败
'a'
打开文件用于写入,如果文件存在则在末尾追加
'b'
二进制模式
't'
文本模式(默认)
'+'
打开用于更新(读取与写入)
encoding
:操作文件时的编码,如果所读文件中包含中文,最好设置为utf-8格式,否则中文读出来会是乱码;如果是读取文件的原生字节的格式,则不能设置encoding。
buffering
:是否采用行缓冲,0:不采用(适用于二进制模式),默认为1
默认的缓冲策略
* 二进制文件以固定大小的块进行缓冲;使用启发式方法选择缓冲区的大小,尝试确定底层设备的“块大小”或使用 io.DEFAULT_BUFFER_SIZE。在许多系统上,缓冲区的长度通常为4096或8192字节。
* “交互式”文本文件( isatty() 返回 True 的文件)使用行缓冲。其他文本文件使用上述策略用于二进制文件。
errors
:可选字符串参数,用于指定如何处理编码和解码错误 - 这不能在二进制模式下使用。
newline
:控制 universal newlines 模式如何生效(它仅适用于文本模式)。它可以是 None,'','\n','\r' 和 '\r\n,主要在读取流或者写入流时做处理,具体如下:
读取流时:如果newlines为None,则启用通用的换行模式,也可以使用其他可选参数
写入流时: 如果newlines为None,则会默认将\n转换为系统分隔符(os.linesep),如果不为None,则使用给定字符串
closefd
:关闭文件描述符(只在file为文件描述符
的情况下生效,否则会报错),默认为True,关闭文件描述符,当为False时,文件描述符在操作时会出现,文件关闭后,对应的文件描述符不会关闭。
opener
:自定义开启器,注意必须要返回一个文件描述符,正常默认为None即可,详单与os.open() as opener
open方法返回了一个文件对象,其实就是IO对象,我们需要知道IO对象中部分方法或者函数。
read(size)
: 读取内容,按照size的大小读取内容,可能会出现裁切的情况,当文件足够大时,size的大小决定了程序占用内存的大小,建议不要太大。readable()
:是否可以读取流,可以则返回True,反之为False,当为False时则无法读取文件流内容。readline(size=- 1)
:一行一行读取,可以设置size大小,代表最多读取的大小,主要是对于一些异常情况,例如一行有比较长的字符的时候readlines(hint=- 1)
:读取整个文件的内容并安装换行符进行输出,返回一个列表,hint可以指定读取的行数。官方建议,如果可以使用 for line in file,就不需要使用for line in file.readlines()writable()
:是否可以写入流,可以则返回True,反之为False,当为False时无法写入文件。writelines(lines)
: 写入多行数据,传入的是序列,默认会在每一个序列中的元素后添加换行write(line: str)
:写入单行数据,传入的字符串isatty()
: 如果流是交互式的(即连接到终端/tty设备),则返回 True
fileno()
: 返回流的底层文件描述符(整数)---如果存在。如果 IO 对象不使用文件描述符,则会引发 OSError 。
tell()
:返回当前流的位置。与seek()中位置类似。需要注意的是,想要获取正确的位置,不能使用如下方式进行操作,会出现下方问题。
with open(file_path, mode="r") as f:
for line in f:
print(line)
print(f.tell())
OSError: telling position disabled by next() call
需要使用readline逐行读取
with open(file_path, mode="r") as f:
while True:
line = f.readline()
print(line)
if not line:
break
print(f.tell())
seekable()
:如果流支持随机访问则返回 True。 如为 False,则 seek(), tell() 和 truncate() 将引发 OSError。
seek(offset, whence=SEEK_SET)
:将流位置修改到给定的字节 offset。 offset 将相对于由 whence 指定的位置进行解析。 whence 的默认值为 SEEK_SET。 需要注意的是seek的偏移量是相对于字符的,不是相对于行数的,whence 的可用值有:
SEEK_SET 或 0 -- 流的开头(默认值);offset 应为零或正值
SEEK_CUR or 1 -- 当前流位置;offset 可以为负值
SEEK_END or 2 -- 流的末尾;offset 通常为负值
fileno()
:返回流的底层文件描述符(整数)---如果存在。如果 IO 对象不使用文件描述符,则会引发 OSError 。
flush()
:刷新流的写入缓冲区(如果适用)。因为某些情况下,在写入时会首先写入到缓冲区,为了保证数据全部写入,可以手动调用flush,这对只读和非阻塞流不起作用。
返回新的绝对位置。
truncate(size=None)
:将流的大小调整为给定的 size 个字节(如果未指定 size 则调整至当前位置)。 当前的流位置不变。 这个调整操作可扩展或减小当前文件大小。 在扩展的情况下,新文件区域的内容取决于具体平台(在大多数系统上,额外的字节会填充为零)。 返回新的文件大小。在 3.5 版更改: 现在Windows在扩展时将文件填充为零。
close()
: 刷新并关闭此流。如果文件已经关闭,则此方法无效。文件关闭后,对文件的任何操作(例如读取或写入)都会引发 ValueError 。为方便起见,允许多次调用此方法。但是,只有第一个调用才会生效。
closed
:如果流已关闭,则返回 True。
with open(file_path, mode="r", encoding="utf-8") as f, open(
file_path2, mode="w", encoding="utf8"
) as w_f:
for line in f:
print(line)
w_f.write(line)
with open(file_path, mode="r") as f:
while True:
line = f.readline()
print(line)
if not line:
break
print(f.tell())
假设存在test.cpp,我们需要在#include
前后添加相应的内容,替换内容均为add_test.
/**
* @file test.cpp
*
*/
#include <glog/logging.h>
int main(int argc, char *argv[])
{
google::InitGoogleLogging(argv[0]);
FLAGS_alsologtostderr = true;
LOG(INFO) << "------conan test-----------------";
google::ShutdownGoogleLogging();
return 0;
}
import pathlib
from pathlib import Path
def content_before_add(file_path: Path, add_content: str):
"""add before content
Args:
file_path (Path): file to be operated
add_content (str): What needs to be added
"""
new_file_path = file_path.parent.joinpath(file_path.name + ".bak")
with open(file_path, mode="r", encoding="utf-8") as r_f, open(
new_file_path, mode="w", encoding="utf-8"
) as w_f:
old_index = -1
for line in r_f:
w_f.write(line)
if line.strip().startswith("#"):
w_f.seek(old_index)
w_f.write(add_content + "\n" + line)
old_index = w_f.tell()
new_file_path.replace(file_path)
def content_after_add(file_path: Path, add_content: str):
"""add after content
Args:
file_path (Path): file to be operated
add_content (str): What needs to be added
"""
new_file_path = file_path.parent.joinpath(file_path.name + ".bak")
with open(file_path, mode="r", encoding="utf-8") as r_f, open(
new_file_path, mode="w", encoding="utf-8"
) as w_f:
for line in r_f:
w_f.write(line)
if line.strip().startswith("#"):
w_f.write(add_content + "\n")
new_file_path.replace(file_path)
替换后内容如下:
/**
* @file test.cpp
*
*/
add_test
#include <glog/logging.h>
int main(int argc, char *argv[])
{
google::InitGoogleLogging(argv[0]);
FLAGS_alsologtostderr = true;
LOG(INFO) << "------conan test-----------------";
google::ShutdownGoogleLogging();
return 0;
}
1.需要注意对于文件操作时候的模式,w
默认会覆盖文件, a
默认会追加文件中的内容。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章