Step By Step(Lua输入输出库)
Step By Step(Lua输入输出库)
I/O库为文件操作提供了两种不同的模型,简单模型和完整模型。简单模型假设一个当前输入文件和一个当前输出文件,他的I/O操作均作用于这些文件。完整模型则使用显式的文件句柄,并将所有的操作定义为文件句柄上的方法。
1. 简单模型:
I/O库会将进程标准输入输出作为其缺省的输入文件和输出文件。我们可以通过io.input(filename)和io.output(filename)这两个函数来改变当前的输入输出文件。
1). io.write函数:
函数原型为io.write(...)。该函数将所有参数顺序的写入到当前输出文件中。如:
io.write("hello","world") --写出的内容为helloworld
2). io.read函数:
下表给出了该函数参数的定义和功能描述:
| 参数字符串 | 含义 |
| "*all" | 读取整个文件 |
| "*line" | 读取下一行 |
| "*number" | 读取一个数字 |
| <num> | 读取一个不超过<num>个字符的字符串 |
调用io.read("*all")会读取当前输入文件的所有内容,以当前位置作为开始。如果当前位置处于文件的末尾,或者文件为空,那个该调用返回一个空字符串。由于Lua可以高效的处理长字符串,因此在Lua中可以先将数据从文件中完整读出,之后在通过Lua字符串库提供的函数进行各种处理。
调用io.read("*line")会返回当前文件的下一行,但不包含换行符。当到达文件末尾时,该调用返回nil。如:
1 for count = 1,math.huge do
2 local line = io.read("*line") --如果不传参数,缺省值也是"*line"
3 if line == nil then
4 break
5 end
6 io.write(string.format("%6d ",count),line,"\n")
7 end
如果只是为了迭代文件中的所有行,可以使用io.lines函数,以迭代器的形式访问文件中的每一行数据,如:
1 local lines = {}
2 for line in io.lines() do --通过迭代器访问每一个数据
3 lines[#lines + 1] = line
4 end
5 table.sort(lines) --排序,Lua标准库的table库提供的函数。
6 for _,l in ipairs(lines) do
7 io.write(l,"\n")
8 end
调用io.read("*number")会从当前输入文件中读取一个数字。此时read将直接返回一个数字,而不是字符串。"*number"选项会忽略数字前面所有的空格,并且能处理像-3、+5.2这样的数字格式。如果当前读取的数据不是合法的数字,read返回nil。在调用read是可以指定多个选项,函数会根据每个选项参数返回相应的内容。如:
1 --[[
2 6.0 -3.23 1000
3 ... ...
4 下面的代码读取注释中的数字
5 --]]
6 while true do
7 local n1,n2,n3 = io.read("*number","*number","*number")
8 if not n1 then
9 break
10 end
11 print(math.max(n1,n2,n3))
12 end
调用io.read(<num>)会从输入文件中最多读取n个字符,如果读不到任何字符,返回nil。否则返回读取到的字符串。如:
1 while true do
2 local block = io.read(2^13)
3 if not block then
4 break
5 end
6 io.write(block)
7 end
io.read(0)是一种特殊的情况,用于检查是否到达了文件的末尾。如果没有到达,返回空字符串,否则nil。
2. 完整I/O模型:
Lua中完整I/O模型的使用方式非常类似于C运行时库的文件操作函数,它们都是基于文件句柄的。
1). 通过io.open函数打开指定的文件,并且在参数中给出对该文件的打开模式,其中"r"表示读取,"w"表示覆盖写入,即先删除文件原有的内容,"a"表示追加式写入,"b"表示以二进制的方式打开文件。在成功打开文件后,该函数将返回表示该文件的句柄,后面所有基于该文件的操作,都需要将该句柄作为参数传入。如果打开失败,返回nil。其中错误信息由该函数的第二个参数返回,如:
assert(io.open(filename,mode)) --如果打开失败,assert将打印第二个参数给出的错误信息。
2). 文件读写函数read/write。这里需要用到冒号语法,如:
1 local f = assert(io.open(filename,"r"))
2 local t = f:read("*all") --对于read而言,其参数完全等同于简单模型下read的参数。
3 f:close()
此外,I/O库还提供了3个预定义的文件句柄,即io.stdin(标准输入)、io.stdout(标准输出)、io.stderr(标准错误输出)。如:
io.stderr:write("This is an error message.")
事实上,我们也可以混合使用简单模式和完整模式,如:
1 local temp = io.input() --将当前文件句柄保存
2 io.input("newInputfile") --打开新的输入文件
3 io.input():close() --关闭当前文件
4 io.input(temp) --恢复原来的输入文件
3). 性能小技巧:
由于一次性读取整个文件比逐行读取要快一些,但对于较大的文件,这样并不可行,因此Lua提供了一种折中的方式,即一次读取指定字节数量的数据,如果当前读取中的最后一行不是完整的一行,可通过该方式将该行的剩余部分也一并读入,从而保证本次读取的数据均为整行数据,以便于上层逻辑的处理。如:
local lines,rest = f:read(BUFSIZE,"*line") --rest变量包含最后一行中没有读取的部分。
下面是Shell中wc命令的一个简单实现。
1 local BUFSIZE = 8192
2 local f = io.input(arg[1]) --打开输入文件
3 local cc, lc, wc, = 0, 0, 0 --分别计数字符、行和单词
4 while true do
5 local lines,rest = f:read(BUFSIZE,"*line")
6 if not lines then
7 break
8 end
9 if rest then
10 lines = lines .. rest .. "\n"
11 end
12 cc = cc + #lines
13 --计算单词数量
14 local _, t = string.gsub(lines."%S+","")
15 wc = wc + t
16 --计算行数
17 _,t = string.gsub(line,"\n","\n")
18 lc = lc + t
19 end
20 print(lc,wc,cc)
4). 其它文件操作:
如io.flush函数会将io缓存中的数据刷新到磁盘文件上。io.close函数将关闭当前打开的文件。io.seek函数用于设置或获取当前文件的读写位置,其函数原型为f:seek(whence,offset),如果whence的值为"set",offset的值则表示为相对于文件起始位置的偏移量。如为"cur"(默认值),offset则为相对于当前位置的偏移量,如为"end",则为相对于文件末尾的偏移量。函数的返回值与whence参数无关,总是返回文件的当前位置,即相对于文件起始处的偏移字节数。offset的默认值为0。如:
1 function fsize(file)
2 local current = file:seek() --获取当前位置
3 local size = file:seek("end") --获取文件大小
4 file:seek("set",current) --恢复原有的当前位置
5 return size
6 end
最后需要指出的是,如果发生错误,所有这些函数均返回nil和一条错误信息。
Step By Step(Lua输入输出库)的更多相关文章
- Lua输入输出库
1.简单模型 )1.io.write函数: 函数模型为io.write(...) )2.io.read函数: io.read(“*all”) 读取当前输入的整个文件 io.read(”*line“) ...
- Step By Step(Lua字符串库)
Step By Step(Lua字符串库) 1. 基础字符串函数: 字符串库中有一些函数非常简单,如: 1). string.len(s) 返回字符串s的长度: 2). string ...
- Step By Step(Lua系统库)
Step By Step(Lua系统库) Lua为了保证高度的可移植性,因此,它的标准库仅仅提供了非常少的功能,特别是和OS相关的库.但是Lua还提供了一些扩展库,比如Posix库等.对于文件操作而言 ...
- Step By Step(Lua模块与包)
Step By Step(Lua模块与包) 从Lua 5.1开始,我们可以使用require和module函数来获取和创建Lua中的模块.从使用者的角度来看,一个模块就是一个程序库,可以通过requi ...
- Step By Step(Lua元表与元方法)
Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...
- Step By Step(Lua编译执行与错误)
Step By Step(Lua编译执行与错误) 1. 编译: Lua中提供了dofile函数,它是一种内置的操作,用于运行Lua代码块.但实际上dofile只是一个辅助函数,loadfile才 ...
- Step By Step(Lua函数)
Step By Step(Lua函数) 一.函数: 在Lua中函数的调用方式和C语言基本相同,如:print("Hello World")和a = add(x, y).唯一的 ...
- Step By Step(Lua基础知识)
Step By Step(Lua基础知识) 一.基础知识: 1. 第一个程序和函数: 在目前这个学习阶段,运行Lua程序最好的方式就是通过Lua自带的解释器程序,如: /> l ...
- Step By Step(Lua开篇)
Step By Step(Lua开篇) 一.简介: Lua作为目前最为流行的.免费轻量级嵌入式脚本语言,在很多工业级的应用程序中被广泛应用,如Adobe's Photoshop,甚至是在一些著名的游戏 ...
随机推荐
- docker搭建简单mysql主从
关于MySQL主从模式,如果我们直接在本机上搭建的话,是没法搭建的,只能借助于虚拟机,但有的时候我们又需要搭建一个主从集群,以便于进行一些功能性的测试.这个时候我们就可以尝试使用docker,借助于d ...
- Word 查找和替换字符串方法
因为项目需要通过word模板替换字符串 ,来让用户下载word, 就在网上找了找word查找替换字符串的库或方法,基本上不是收费,就是无实现,或者方法局限性太大 .docx 是通过xml来存储文字和其 ...
- 整合Atomikos、Quartz、Postgresql的踩坑日记
前言 由于业务需要,在单体Spring Boot项目中需要引入分布式事务,来保证单体应用连接的多个数据源的事务统一. 而说到分布式事务,小伙伴们肯定会想到阿里的Seata,阿里Seata强大的AT模式 ...
- k8s daemonset
DaemonSet控制器会在每个节点上运行单一的副本,他非常适合部署那些节点本身提供服务或者执行维护的 Pod 例如 : 存储相关,每个节点上运行glusterd, ceph 日志收集相关,每个节点上 ...
- 从零开始使用git将本地项目上传到GitHub
直接进入主题 1. 注册GitHub(官网:https://github.com/),打开官网,右上角点击sign up注册按钮,进入注册界面,根据提示填写信息注册.
- system分区解锁
前言 获取root权限,解锁system 步骤 手机设置 设置--更多设置--开发者选项--USB调试给打开 电脑操作 打开cmd adb devices 执行命令 adb root &&am ...
- 【Nacos】Springboot整合Nacos配置中心(二) 多环境配置
本篇随笔接上一篇文章:Springboot整合Nacos配置中心(一),主要记录Nacos多环境的配置的方法 Nacos多环境的配置 方法一: 1.在项目中的bootstrap.yaml文件中配置激活 ...
- PAT 乙级 -- 1011 -- A+B和C
问题简述 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组占一行,顺序 ...
- 2 IDEA——新建一个java项目
快捷键 public class Hello { // psvm public static void main(String[] args) { // sout System.out.println ...
- 初始化mysql报错bin/mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory
原因:缺少libaio.so.1 解决办法:安装即可 yum install -y libaio