Lua教程(十五):输入输出库(I/O库)_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函数:
    下表给出了该函数参数的定义和功能描述:

  调用io.read("*all")会读取当前输入文件的所有内容,以当前位置作为开始。如果当前位置处于文件的末尾,或者文件为空,那个该调用返回一个空字符串。由于Lua可以高效的处理长字符串,因此在Lua中可以先将数据从文件中完整读出,之后在通过Lua字符串库提供的函数进行各种处理。

    调用io.read("*line")会返回当前文件的下一行,但不包含换行符。当到达文件末尾时,该调用返回nil。如:
 

复制代码 代码如下:

 for count = 1,math.huge do
    local line = io.read("*line")  --如果不传参数,缺省值也是"*line"
    if line == nil then
        break
    end
    io.write(string.format("%6d  ",count),line,"\n")
end
 

    如果只是为了迭代文件中的所有行,可以使用io.lines函数,以迭代器的形式访问文件中的每一行数据,如:

复制代码 代码如下:

local lines = {}
for line in io.lines() do   --通过迭代器访问每一个数据
    lines[#lines + 1] = line
end
table.sort(lines)  --排序,Lua标准库的table库提供的函数。
for _,l in ipairs(lines) do
    io.write(l,"\n")
end

    调用io.read("*number")会从当前输入文件中读取一个数字。此时read将直接返回一个数字,而不是字符串。"*number"选项会忽略数字前面所有的空格,并且能处理像-3、+5.2这样的数字格式。如果当前读取的数据不是合法的数字,read返回nil。在调用read是可以指定多个选项,函数会根据每个选项参数返回相应的内容。如:

复制代码 代码如下:

--[[
    6.0  -3.23   1000
    ... ...
    下面的代码读取注释中的数字
--]]
while true do
    local n1,n2,n3 = io.read("*number","*number","*number")
    if not n1 then
        break
    end
    print(math.max(n1,n2,n3))
end

    调用io.read(<num>)会从输入文件中最多读取n个字符,如果读不到任何字符,返回nil。否则返回读取到的字符串。如:

复制代码 代码如下:

while true do
    local block = io.read(2^13)
    if not block then
        break
    end
    io.write(block)
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。这里需要用到冒号语法,如:

复制代码 代码如下:

 local f = assert(io.open(filename,"r"))
 local t = f:read("*all")  --对于read而言,其参数完全等同于简单模型下read的参数。
 f:close()

    此外,I/O库还提供了3个预定义的文件句柄,即io.stdin(标准输入)、io.stdout(标准输出)、io.stderr(标准错误输出)。如:
    io.stderr:write("This is an error message.")
    事实上,我们也可以混合使用简单模式和完整模式,如:

复制代码 代码如下:

 local temp = io.input()   --将当前文件句柄保存
 io.input("newInputfile")  --打开新的输入文件
 io.input():close()        --关闭当前文件
 io.input(temp)            --恢复原来的输入文件

  3). 性能小技巧:

    由于一次性读取整个文件比逐行读取要快一些,但对于较大的文件,这样并不可行,因此Lua提供了一种折中的方式,即一次读取指定字节数量的数据,如果当前读取中的最后一行不是完整的一行,可通过该方式将该行的剩余部分也一并读入,从而保证本次读取的数据均为整行数据,以便于上层逻辑的处理。如:
    local lines,rest = f:read(BUFSIZE,"*line") --rest变量包含最后一行中没有读取的部分。

    下面是Shell中wc命令的一个简单实现。

复制代码 代码如下:

local BUFSIZE = 8192
local f = io.input(arg[1])  --打开输入文件
local cc, lc, wc, = 0, 0, 0  --分别计数字符、行和单词   
while true do
    local lines,rest = f:read(BUFSIZE,"*line")
    if not lines then
        break
    end
    if rest then
        lines = lines .. rest .. "\n"
    end
    cc = cc + #lines
    --计算单词数量
    local _, t = string.gsub(lines."%S+","")
    wc = wc + t
    --计算行数
    _,t = string.gsub(line,"\n","\n")
    lc = lc + t
end
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。如:

复制代码 代码如下:

 function fsize(file)
     local current = file:seek()   --获取当前位置
     local size = file:seek("end") --获取文件大小
     file:seek("set",current)      --恢复原有的当前位置
     return size
 end

    最后需要指出的是,如果发生错误,所有这些函数均返回nil和一条错误信息。

时间: 2024-09-05 21:15:11

Lua教程(十五):输入输出库(I/O库)_Lua的相关文章

Lua教程(十七):C API简介_Lua

Lua是一种嵌入式脚本语言,即Lua不是可以单独运行的程序,在实际应用中,主要存在两种应用形式.第一种形式是,C/C++作为主程序,调用Lua代码,此时可以将Lua看做"可扩展的语言",我们将这种应用称为"应用程序代码".第二种形式是Lua具有控制权,而C/C++代码则作为Lua的"库代码".在这两种形式中,都是通过Lua提供的C API完成两种语言之间的通信的. 1. 基础知识: C API是一组能使C/C++代码与Lua交互的函数.其中包括读

PostgreSQL教程(十五):系统表详解_PostgreSQL

一.pg_class:     该系统表记录了数据表.索引(仍然需要参阅pg_index).序列.视图.复合类型和一些特殊关系类型的元数据.注意:不是所有字段对所有对象类型都有意义.   名字 类型 引用 描述 relname name   数据类型名字. relnamespace oid pg_namespace.oid 包含这个对象的名字空间(模式)的OI. reltype oid pg_type.oid 对应这个表的行类型的数据类型. relowner oid pg_authid.oid

Lua教程(五):C/C++操作Lua数组和字符串示例_Lua

本文将介绍如何在C/C++里面操作Lua的数组和字符串类型,同时还会介绍如何在C/C++函数里面存储Lua状态(registry和upvalue),而registry在使用C/C++自定义类型时非常有用,可以方便地为userdata指定metatable. C/C++操作Lua数组 Lua数组Overview 在Lua里面,数组只不过是key为整数的table而已.比如一个table为array = {12,"Hello", "World"},它是一个数组,可以用下

FrontPage 2003基础教程(十五) 共享边框

1.启用共享边框: >"工具">"网页选项">"创作">选中"共享边框" 2."格式"中选中"共享边框"在对话框中(注:若想损事,选:所有网页)设置选项"上.左.右.下"(可以自定) 3.在自动出现的共享边框中编辑链接栏属性 4.最后的效果 5.和上一讲的链接栏配合使用,当你每添加一个网页在链接栏中会自动生成上面的效果 查看全套FrontPag

Redis教程(十五):C语言连接操作代码实例_Redis

在之前的博客中已经非常详细的介绍了Redis的各种操作命令.运行机制和服务器初始化参数配置.本篇博客是该系列博客中的最后一篇,在这里将给出基于Redis客户端组件访问并操作Redis服务器的代码示例.然而需要说明的是,由于Redis官方并未提供基于C接口的Windows平台客户端,因此下面的示例仅可运行于Linux/Unix平台.但是对于使用其它编程语言的开发者而言,如C#和Java,Redis则提供了针对这些语言的客户端组件,通过该方式,同样可以达到基于Windows平台与Redis服务器进行

Lua教程(五):迭代器和泛型for_Lua

1. 迭代器与Closure:     在Lua中,迭代器通常为函数,每调用一次函数,即返回集合中的"下一个"元素.每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置和下一次遍历时的位置.从这一点看,Lua中closure机制为此问题提供了语言上的保障,见如下示例: 复制代码 代码如下: function values(t)     local i = 0     return function()         i = i + 1         return

Android简明开发教程十五:RadioButton多边形及路径绘制

这个例子是绘制多边形,多义形和路径,采用单选钮RadioButton来选择Polys 和Path示例: UI 设计为 上部分用来显示绘图内容,下部分为两个单选按钮 Polys ,Path.这样layout就和main.xml 不一样,main.xml 只含一个com.pstreets.graphics2d.GuidebeeGraphics2DView.因此需在res/layout下新建一个polys.xml: <?xml version="1.0″ encoding="utf-8

Lua教程(三):值与类型介绍_Lua

Lua 是一种 动态类型语言. 这意味着变量没有类型,只有值才有类型. 语言中不存在类型定义.而所有的值本身携带它们自己的类型信息. Lua 中的所有值都是一致 (first-class) 的. 这意味着所有的值都可以被放在变量里,当作参数传递到另一个函数中,并被函数作为结果返回. Lua 中有八种基本类型: nil, boolean, number, string, function, userdata, thread, and table. Nil 类型只有一种值 nil ,它的主要用途用于

Lua教程(四):函数详解_Lua

一.函数:     在Lua中函数的调用方式和C语言基本相同,如:print("Hello World")和a = add(x, y).唯一的差别是,如果函数只有一个参数,并且该参数的类型为字符串常量或table的构造器,那么圆括号可以省略,如print "Hello World"和f {x = 20, y = 20}.     Lua为面对对象式的调用也提供了一种特殊的语法--冒号操作符.表达式o.foo(o,x)的另一种写法是o:foo(x).冒号操作符使调用o

Lua教程(三):表达式和语句_Lua

一.表达式:     1. 算术操作符:     Lua支持常规算术操作符有:二元的"+"."-"."*"."/"."^"(指数)."%"(取模),一元的"-"(负号).所有这些操作符都可用于实数.然而需要特别说明的是取模操作符(%),Lua中对该操作符的定义为:   复制代码 代码如下:     a % b == a - floor(a / b) * b