io库 读写文件

io库提供标准输入输出,文件流操作函数,

如果是一次性读写文件数据,应优先选择:string库文件读写函数

打开文件

1、函数原型:

file = io.open ( 文件路径, mode="r",共享模式 )


2、函数说明:

io.open 「外部文件」,创建并返回文件流对象。
文件路径为空则创建可读写的临时文件,并返回该文件的流对象, 如果省略文件路径参数则打开控制台窗口.

使用共享模式打开文件对象,请参考:string库文件读写函数

 

共享模式可选参数:

io.open默认以共享模式打开文件,可选使用第三个参数指定独占模式.
支持以下参数(多个参数可使用 | 连接)

0x10 /* _SH_DENYRW */ 独占读写权限
0x20 /* _SH_DENYWR */ 独占写权限
0x30 /* _SH_DENYRD */ 独占读权限
0x40 /* _SH_DENYNO */ 共享模式(默认模式),外部程序可读写该文件
0x80 /* _SH_SECURE */ 安全模式

mode参数可选的格式如下

一、读、写、追加模式

"r": 读模式(默认模式),文件必须存在
"w": 写模式,文件不存在就新建文件
"a": 追加模式,文件不存在就新建文件,如希望打开文件用于写,又不要删除原文件中的数据,并从原文件的末尾开始添加新的数据,应该使用此模式

必须使用r,w,a其中之一作为模式标记的第一个字符. 且只能作为第一个字符.

二、读写复合模式

"r+": 打开可读写的文件,该文件必须存在。写入的数据会被加到文件尾后。
"w+": 打开或创建可读写文件,若文件不存在则建立该文件。文件原先的内容会被清除。
"a+": 以附加方式打开或创建可读写的文件,若文件不存在则会建立该文件,文件原先的内容会被保留(如果文件存在,写入的数据会被加到文件尾后)。

注意:
r,r+ 都要求文件必须存在,
w,w+,a,a+ 如果发现文件不存在则会创建文件.
w与a的区别在于:w会清空原来的文件内容,而a不会
有+号与没+号的区别在于: 有+号表示可读可写,而没有+号要么是可读而不可写,可么是可写而不可读

三、附加标志

模式后添加t表示以文本模式访问,添加b表示以二进制模式访问。
例如 "rb" 表示以二进制读模式打开文件。

io.open函数默认使用文本模式,
string.load() string.save() 等函数则默认以二进制模式读写文件.

使用文本模式时aardio会保证读取的文本以'\n'换行( 参考:回车换行符 ),
但是文本模式打开文件时,'\0'被认为是终止符. 如果你要使用io.open()函数打开二进制文件读写,请务必显式指定'b'模式.

1、a,w,r等只能出现在第一个标记
用a+ w+ r+表示扩展的属性,如r+表示可读写,而不是rw

'S' 连续模式
'R' 随机模式

'D' 打开为临时文件,关闭文件对象时自动删除文件。

io.stdout,io.stderr,io.stdin可以在读写模式中使用ccs字段指定文件的存储编码并在输入输出过程中支持自动转换编码, 例如"w,ccs=UTF-8","w,ccs=UTF-16LE","w,ccs=UNICODE",但只能在将标准输出重定向到硬盘文件时才能正常使用,编码只能指定这三种, 如果文件指定了BOM则以文件BOM实际声明的编码为准,当标准输入输出流重定向到控制台时只能指定普通文本模式不允许使用ccs标记, 使用ccs标记指定错误的编码,或者使用了二进制读写函数都会导致程序不可预料的异常,这个功能一般不建议大家使用, 因为aardio的默认编码就是UTF8,而且在aardio中转换编码也非常方便,并不需要用到这个功能。

3、调用示例:

io.open() //参数为空则打开控制台窗口。
tempfile = io.open("") //文件名为空则创建可读写的临时文件

如果需要在打开文件时自动捕获错误,可以这样写:

//io.open在打开文件失败时会返回两个参数: null,错误信息
//而assert函数在接收的第一个参数为null时断言失败,并会将第二个参数作为错误信息抛出异常

var file = assert(io.open("nofile.txt", "rb") )

请参考: assert

关闭文件

file.close() 关闭使用io.open打开的文件file对象。

写文件

file.write(...);

file.write获取任意数目的数字、字符串参数、或结构体(struct table),接着将它们写入到输出文件流。

file = io.open("");

file.write("hello" + "world"); //不建议使用字符串连接
file.write("hello", "world"); //直接用多个参数更快更好

file.write 支持参数中使用静态类型定义的结构体,如果是一个结构体,file.write将之转换为二进制并直接写入文件.

输出缓冲

file.flush()
输入缓冲区内容到文件中,以保存对文件的修改。
通常写入的内容在调用file.flush函数或者file.close函数才会保存到文件中。

读文件

file.read(...)

read函数从当前输入文件读取串,由它的参数控制读取的内容。
参数可以有多个,参数要设置的选项如下:

str = file.read("%s"): 读取下一行文本

函返回当前输入文件的下一行(不包含最后的换行符)。
当到达文件末尾,返回值为null(表示没有下一行可返回)。
该读取方式是read函数的默认方式,所以可以简写为file.read()。

int = io.read("%d"): 从串中转换出数值

函数从当前输入文件中读取出一个数值(而不是字符串)。
当需要从一个文件中读取大量数字时,数字间的字符串为空白可以显著的提高执行性能。
%d选项会跳过两个可被识别数字之间的任意空格。这些可识别的字符串可以是-3, +5.2, 1000,和 -3.4e-23。
如果在当前位置找不到一个数字(由于格式不对,或者是到了文件的结尾),
则返回null

可以对每个参数设置选项,函数将返回各自的结果。例如:
n1,n2,n3 = file.read("%d","%d","%s"):

str = file.read(n)

read函数将尝试从输入文件中读取n个字节。
如果无法读取到任何字符(已经到了文件末尾),函数返回null。否则返回一个最多包含n个字符的串。

str = file.read(0)

用来测试是否到达了文件末尾。如果不是返回一个空串,如果已是文件末尾返回null。

str = file.read(-1):

如果为负数,表示从当前位置读取内容到文件尾部倒计数的指定位置。失败返回null.
-1表示读取到文件尾部, 如果参数为-1,则失败返回空串而不是null。

str = file.read(struct):

函数从获取一个结构体(struct table)的长度,并从文件中读取数据到结构体中。
如果当前位置在文件末尾,或者文件为空,函数将返回null。

反向读文件

str = file.readback(n)

此函数与file.read类似,不同的是它从后向前移动文件指针并读取指定长度的内容.
如果没有指定长度,则向前读取一行.

该函数不支持多参数,也不支持除数值以外的参数

参数如果是0,测试是否到达文件头,返回值可用于条件表达式。
参数如果是正数n,则从当前位置向前读取n个字节。
参数如果是负数-n,则从当前位置向前读取到文件头倒数n个字节所在位置。

无参数则向前读取一行。
不支持其他格式参数,不支持多参数。

移动文件指针

file.seek(whence="cur",offset=0)

offset指定偏移量。
whence参数指定偏移方式,offset指定偏移量。
返回值为读写指针的当前位置。

whence参数可选项如下
"set",偏移值是从文件头开始;
"cur",偏移值从当前位置开始;
"end",偏移值从文件尾往前计数

whence的默认值为"cur",offset的默认值为0。
offset = file.seek()得到的返回值就是文件当前的存取位置,且保持位置不变。
file.seek("set")就是将文件的存取位置重设到文件开头。
而offset = file.seek("end")就是将位置设为文件尾,同时就可以得到文件的大小。

如果需要得到文件的大小又不改变读写指针的位置,可以这样写

var current = file.seek() //得到读写指针当前位置
var size = file.seek("end") //得到文件大小
file.seek("set", current) //恢复读写指针当前位置

设置缓冲区

file.setvbuf (mode [, size])

设置写入文件流使用的缓冲区,
第一个参数指定缓冲区模式,支持以下三种模式:

"no": 无缓冲区.
"full": 使用完全缓冲
"line": 使用行缓冲

第二个参数指定缓冲区大小。