《Programming in Lua 3》读书笔记(十八)

2023-05-16

日期:2014.7.28
PartⅢ The Standard Libraries

22 The I/O Library


        Lua的I/O库提供了两种不同的文件处理模式。简单模式以I/O操作是基于当前的输入文件和输出文件的;而完全模式则提供了完整的文件处理方式,这种方式采用了面向对象的思想,将所有操作都处理为各种方法。
简单模式对一般上的I/O操作来说是非常方便的,而有些时候例如同时处理多个文件的情况则需要完全模式了。


22.1 The Simple I/O Model
       简单模式对两个current file处理其所有的操作。标准库将当前输入文件(current input file)初始化为标准输入(stdin)处理,而将输出文件(current output file)初始化为标准输出(stdout)处理。因此当我们实现如io.read()功能的时候,我们实际上是通过标准输入(standard input)来读取数据的。
       我们可以使用io.input 和 io.output函数来改变这些输入输出文件。io.input(filename)打开了指定名字的文件,然后设定了之后的输入文件都是这个文件,知道再通过io.input改变来改变;io.output则可以针对输出工作做出类似的处理。而针对错误处理,两个函数都可以抛出错误,但是要立即处理这些错误则需要使用完全模式。
       首先介绍write函数(作者的意识是write比read更简单),该函数接受任意数量的字符串型参数然后将这些字符串型变量写进当前的输出文件中,该函数遵循通用的转换规则进行数值转字符串处理;而如果想完整的控制这种转换,则需要使用string.format函数:

e.g.
--Simple Mode
io.write("sin(3) = ",math.sin(3),"\n")
--sin(3) = 0.14112000805987

io.write(string.format("sin(3) = %.4f\n",math.sin(3)))
--sin(3) = 0.1411

      要注意避免写:io.wirte(a..b..c)这样的格式,lua实现io.write(a,b,c)操作使用的资源会更少。
      作为一个约定:在debugging过程中应该使用print函数,而只有在需要严格做输出格式控制的时候使用write函数:

e.g.
print("hello","Lua");print("Hi")
--hello     Lua
--Hi
io.write("hello","Lua");io.write("HI","\n")
--helloLuaHI

       write函数在输出的时候不会额外的添加字符(如tab和下一行)。不仅如此,write函数允许改变输出函数,而print总是使用标准输出(standard output)。最后,print会自动对参数执行tostring操作,这对于debugging来说是挺方便的,但是这可能会在你稍不注意的时候隐藏了一些bug。

       io.read函数从输入文件中读取字符串,该函数的参数控制该读取什么:
"*a"               读取整个文件
"*l"                读取下一行(没有 newline字符)
"*L"               读取下一行(有 newline)
"*n"               读取一个数字
num               读取字符串直到遇到数值字符

        io.read("*a") 读取整个输入文件,当到达输入文件末尾或者输入文件为空的时候,返回一个空字符串;
        因为lua处理长字符串是高效的,因此如果想控制输出过滤可以首先使用read函数将整个文件执行写入操作成为一个字符串,然后通过string的标准库函数gsub做下一步处理,最后使用write函数进行输出:

e.g.
t = io.read("*a")
t = string.gsub(t, …)     --do something
io.write(t)

       io.read("*l")/io.read("*L")当到达了文件的末尾,函数返回nil;
       io.read("*n") 从当前的输入文件中读取一个数字。这是read函数返回一个数值的唯一情况,*n 会跳过空格并且接受所有的数值格式:-3,+5.2等。当该函数从当前的输入文件中找不到数值的时候,将会返回nil。
       read函数可以接受多个控制参数,对于每个参数,函数会返回相应的结果,如果一行文件有三个数,我们需要读取这些数据然后得到最大值:

6.0     -3.23     15e12
4.3     234        100001
…
e.g.
while true do
     local n1,n2,n3 = io.read("*n","*n","*n)
     if not n1 then break end
     print(math.max(n1,n2,n3))
end

        除去这些基本的read模式,也可以传递一个数值n调用read函数,这种情况下read会试图从输入文件中读取n个字符,如果不能从文件中读取任何字符那么将会返回nil,否则会返回最多由n个字符组成的字符串。以下例子介绍了一个高效的从stdin复制文件到stdcout的方法:

e.g.
while true do
     local block = io.read(2^13)
     if not block then break end
     io.write(block)
end

       io.read(0)具有特殊用途:用来测试是否达到了文件结尾,在还能读取的时候将会返回一个空的字符串否则将会返回nil。



22.2 The Complete I/O Model
      这种模式是为了在I/O操作时能提供更多的控制方法。这种模式的核心概念是——文件句柄,相当于C中的stream(FILE*):it represents an open file with a current position(代表着当前打开的文件及当前读取的位置).
      为了打开一个文件,使用io.open函数,参数是文件名和另一个用来控制模式的字符串参数:'r'代表打开文件用来读取,'w'代表打开文件用来写入(会擦除打开的文件中在该位置之前的文件内容),'a’代表打开文件用来在末尾追加内容,可选指令'b'用来打开二进制文件,如:'rb',打开二进制文件用来读取。open函数返回一个新的句柄,在遇到错误的时候,函数返回nil+错误信息和一个错误代码:

e.g.
print(io.open("non-existent-file","r"))
     -- nil no-existent-file:No such file or directory 2
print(io.open("/etc/passwd","w"))
     --nil  /etc/passwd:Permission denied 13

       错误代码表示的意思依系统而定。

       检查错误的小技巧:

e.g.
local f = assert(io.open(filename,mode))

       打开了一个文件之后,可以使用方法read/write对文件执行读取操作或者写入操作。这些方法类似于read/write函数,只不过现在是以方法进行调用,使用冒号操作符(:),例如:打开一个文件,然后读取其所有内容:

e.g.
local f = assert(io.open(filename,"r"))          --打开文件用来读取内容
local t = f:read("*a")                                   --调用read方法,执行读取全部文件内容的操作
f:close()    

        Lua的标准I/O库提供了三个预定义的C stream句柄:io.stdin,io.stdout,io.stderr.可以使用如下方式给error stream发送错误信息:

e.g.
io.stderr:write(message)

        我们可以混合使用标准模式(简单模式)和完全模式进行I/O处理。可以通过不带参数调用io.input()得到当前的输入文件句柄,可以通过带参数调用io.input(filename)来设置当前的输入文件句柄(io.output也可以执行类似的操作),例如:想临时改变当前的输入文件,可以执行如下操作:

e.g.
local temp = io.input()          --得到当前的输入文件
io.input("new")                     --设置新的输入文件
io.input():close()                  --关闭当前的输入文件
io.input(temo)                     --还原之前的输入文件

       也可以通过io.lines来读取文件。用io.lines来读取文件的时候,该函数的第一个参数可以是一个文件名字也可以是一个文件句柄。当是文件名字的时候,io.lines将会以读取模式打开该文件并且在达到该文件末尾的时候关闭该文件;而当是文件句柄的时候,以该句柄进行文件读取,但是不会在读取之后关闭该文件。当不带参数调用该函数的时候,io.lines会从当前的输入文件中读取内容。
     从Lua5.2开始,io.lines也接受同io.read一样的操作指令作为第二个参数。下面的例子复制一个文件到当前的输出文件中:

for block in io.lines(filename,2^13) do
     io.write(block)
end


A small performance trick
        通常在lua中,一次全部读取一个文件会比一行一行的读要快,但是当读取一个非常大的文件的时候,就需要改变这个策略了。此时最佳的做法是每次读取控制在一个合理范围内的块(作者建议是 8kB),to avoid the problem of breaking lines in the middle(),可以在read函数的参数上做点小技巧:

e.g.
local lines,rest = f:read(size,"*l")
The variable rest will get the rest of any line broken by the chunk,we then concatenate the chunk and this rest of line.this way,the resulting chunk will always break at line boundaries.


Binary files
       标准模式下函数io.input/io.output函数是操作文本格式的文件的。在UNIX中,文本文件和二进制文件是没有区别的,但是在别的系统中,尤其是window系统中,二进制文件必须以特殊的方式打开。为了处理这些二进制文件,必须使用io.open,使用参数'b'.
       Lua处理二进制文件类似于处理普通的文本文件,lua中的字符串可以存入任何字节,而标准库中几乎所有的函数都可以处理二进制字节。也可以使用二进制数据进行模式匹配,当然此时需要使用字符类:%z.
       可以使用'*a",读取整个二进制文件,也可以使用n读取n个字节。以下例子实现的功能是:将windows格式的文本文件转换成UNIX格式。没有使用标准的I/O库(stdin-stdout),因为这些文件是以二进制文本形式打开的;而是假定将输入文件和输出文件的名字作为函数参数使用:

e.g.
local inp = assert(io.open(arg[1],"rb"))
local out = assert(io.open(arg[2],"wb"))
local data = inp:read("*a")
data = string.gsub(data,"\r\n","\n")
out:write(data)
assert(out:close())

使用如下方式调用:

lua prog.lua file.dos file.unix

下面这个例子将从二进制文件中读取到的数据打印出来:

e.g.
local f = assert(io.open(arg[1],"rb"))
local data = f:read("*a")
local validchars = "[%g%s"]
local pattern = "(" .. string.rep(validchars,6) .. "+)\0"
for w in string.gmatch(data,pattern) do
     print(w)
end




22.3 Other Operations on Files
        tmpfile函数返回一个临时文件句柄,以read/write方式打开。被打开的文件会在程序结束的时候自动移除。
flush函数将所有还未写入文件的信息执行写入操作。可以以函数形式使用:io.flush(),将会flush当前的输出文件;也可以以方法形式使用:f:flush(),将特定的文件执行flush操作。
        setvbuf方法:设置stream(流)的buff模式。第一个参数是字符串:“no”表示没有缓冲;“full”表示只有当buff缓存已满或者明确指出flush文件,stream流才会执行操作;“line”表示知道新的一行被输出了或者有从别的特殊文件中有输入操作才会将输出信息进行缓存。而对于后两个可选参数,setvbuf接受一个可选参数作为设定缓存大小。
在大多数系统中,标准error流是没有缓存的,而标准output流是以“line”模式进行缓存,因此使用标准输出流执行了某个操作,需要执行flush操作之后才会看到输出消息。
        seek方法可以设置和获得当前输入输出文件的操作位置。






转载于:https://www.cnblogs.com/zhong-dev/p/4044567.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《Programming in Lua 3》读书笔记(十八) 的相关文章

  • 无法在cmake中使用find_package找到Lua标头

    我正在尝试使用 CMake 为我使用 Lua 的项目构建生成 make 文件 当我运行 make 时出现此错误 path to my project luaudio luaudio c 1 17 fatal error lua h No s
  • 代码说“尝试比较数字<=实例”

    It says Players ninjafox56 PlayerGui Shop ShopGui LightSide ChooseSideL 5 尝试比较数字 Rank game Players LocalPlayer leadersta
  • 为什么这个 Lua 优化 hack 会提高性能?

    我正在寻找一个描述提高 Lua 性能的各种技术的文档 http www lua org gems sample pdf脚本代码 我很震惊竟然需要这样的技巧 虽然我引用的是 Lua 但我在 Javascript 中也见过类似的 hack 为什
  • 如何使用Lua脚本语言打开Web套接字?

    作为初学者 我想在基于 Linux 的服务器上使用 Lua 打开一个 Web 套接字 该服务器应允许 Android 客户端连接到它 你能给我一些用Lua打开网络套接字的示例代码吗 您两周前已经问过同样的问题并得到了回答 LUA 脚本 We
  • 使用 OOP 的闭包方法时如何实现受保护的成员?

    现在我正在使用实施 OOP 的闭包 http lua users org wiki ObjectOrientationClosureApproach在卢阿 下面是一个简短的示例 我的问题发生在尝试实施时stronger heal insid
  • LuaJit FFI 从 C 函数返回字符串到 Lua?

    假设我有这个 C 函数 declspec dllexport const char GetStr static char buff 32 Fill the buffer with some string here return buff 这
  • Lua - 尝试调用全局(零值)

    执行此代码时 出现错误 尝试调用全局 forId 零值 function execute args local itemid 526 local bone forId itemid this is where the error occur
  • Lua中如何获取目录列表

    我需要 LUA 中的目录列表 假设我的目录路径为 C Program Files 我需要该特定路径中所有文件夹的列表以及如何搜索该列表中的任何特定文件夹 Example 需要路径 C Program Files 中所有文件夹的列表 以下是上
  • 循环直到在表中找到 2 个特定值?

    我试图找到一种更聪明的方法来解决这个问题 这是与游戏相关的代码的摘录 它循环遍历每个背包的每个插槽 直到找到铲子和绳子 local continue local foundShovel foundRope for i 0 Container
  • 什么时候适合使用Lua这样的嵌入式脚本语言

    我玩 魔兽世界 大约有两年了 我对用来编写插件的 Lua 很好奇 由于到目前为止我读到的有关 Lua 的内容都是 快 轻 和 这太棒了 所以我想知道如何以及何时使用它 您需要在系统中嵌入像 Lua 这样的脚本语言的典型情况是什么 当您需要最
  • Kong - 验证上游 ssl(ssl_proxy 打开)

    我已经成功为 API 安装了 kong 网关 该 API 通过上游负载平衡到多个目标 应用程序服务器 现在 我有一个我的应用程序服务器的自签名证书 kong 和目标之间的 ssl 握手应该失败 我推断 kong 不验证上游证书 经过一些研究
  • 如何在Conky中实现一个基本的Lua功能?

    我正在尝试向我的 Conky 添加一个函数 该函数打印字符串的长度以用于调试目的 代码位于名为的文件内test lua 非常简单 function test word return string len word end 我这样加载它 在我
  • Lua中如何获取表中的最大整数?

    Lua中如何获取表中的最大整数 在Lua 5 1及更早版本中 你可以使用 math max unpack 1 2 3 4 5 这受到Lua堆栈大小的限制 在 PUC Lua 5 1 上 该值的最大值可达 ca 8000 个数字 如果堆栈空闲
  • 为什么 LuaJIT 这么好?

    编辑 不幸的是 LuaJIT 已从下面链接的比较中删除 This 比较 http shootout alioth debian org u64 which programming languages are fastest php编程语言的
  • 在lua中组合两个函数

    我刚开始学习lua 所以我的要求可能是不可能的 现在 我有一个接受函数的方法 function adjust focused window fn local win window focusedwindow local winframe w
  • Lua 从 5.1 更新 - LUA_GLOBALSINDEX 问题

    我最近将旧的 Lua 5 1 项目更新到了该库的最新版本 但遇到了问题LUA GLOBALSINDEX 它变得不确定 我只用过它lua getfield函数 像这样 void luastartgame void if startgamefu
  • Lua 将字符串转换为数字 - 取决于语言环境

    刚刚注意到字符串 and tonumber 在 Lua 中是依赖于语言环境的 知道如何在不使用的情况下将字符串转换为数字tonumber 谢谢 例如将字符串 58 5 转换为 58 5 另外 当我尝试将带点的数字传递给函数时 该函数会转换
  • 如何在 emacs lua-mode 中配置缩进?

    完整的 emacs 新手在这里 我在 Ubuntu 上使用 emacs 23 1 1emacs 入门套件 https github com technomancy emacs starter kit 我主要在 lua 模式下工作 安装了pa
  • Lua C API:初始化结构体 C 中的变量矩阵

    我正在尝试使用 Lua C API 创建一个用户数据 并在其中关联一个元表 我将在其中收集矩阵 我无法得到的是如何将初始化矩阵的每个分量设置为零 我按照我的描述编译我的 Lua 模块 C 代码here https stackoverflow
  • 如何让我的 add 命令找到第一个变量和第二个变量的值,然后将它们加在一起?

    vars values function open file lex file end function lex file local data io open file r for char in data lines do Print

随机推荐

  • 6个常见校园网认证客户端故障原因及解决方法

    故障 一 xff1a 本地连接打叉或受限制 xff1b 客户端 提示 无法获取IP信息 可能原因 1 xff0e 网线虚接 2 xff0e 学生端网络 跳线质量太差 3 xff0e 网卡 或网卡驱动程序过久 4 xff0e 交换机的某个端口
  • C语言编程 求两个数的平均值方法(三种方法)

    第一种方法是最常见的 average 61 xff08 a 43 b xff09 2这种方式 xff0c 求两个数的平均值 第二种方法是 当 a lt b 时 averag 61 a 43 b a 2 这里着重介绍的是第三种方法 avera
  • IDEA创建GIT分支并提交到其他分支

    1 xff0c 创建分支 2 xff0c 提交自己的分支 3 xff0c 写代码 xff0c 写完之后切换到你想要提交的分支 xff0c 例子develop 切花分支 xff0c 选择分支 xff0c checkOut 4 下载该分支的更新
  • 【C#学习笔记】写文件

    using System using System IO namespace ConsoleApplication class Program static void Main string args FileStream file 61
  • socket编程——一个简单的例子(转)

    原文地址 xff1a http blog csdn net wind19 article details 6156339 从一个简单的使用TCP例子开始socket编程 xff0c 其基本步骤如下 xff1a server client 4
  • BI 多维数据 处理错误

    哎 响应中的错误和警告 后端数据库访问模块中存在错误 OLE DB 报告列 11 出现了数据类型溢出现象 OLAP 存储引擎中存在错误 处理 Fact Order Sales 分区时出错 xff0c 该分区属于 Analysis 数据库的
  • AutoLISPDCL各种控件

    AutoLISP对话框DCL一共包括23个常用控件和8个固定控件 xff0c 每种控件属于一种类型 xff0c 创建一个DCL对话框窗体就是创建各种控件实例的过程 xff0c 控件是各种属性 事件 方法的集合 按照各种控件的特点 xff0c
  • 完整克隆、链接克隆

    在VMware中安装虚拟主机时 xff0c 若想简便快速的部署多台虚拟主机 xff0c 可先配置一台虚拟主机的一些基础设置 xff0c 然后通过 34 克隆 34 的方式快速部署 而 34 克隆 34 又分为完整克隆和链接克隆 xff1a
  • 急求mapx控件下载!!!

    急求mapx控件下载 Delphi Windows SDK API http www delphi2007 net DelphiMultimedia html delphi 2006121723132453 html 刚刚在网上搜了好久 没
  • 【Android】Mac安装EasyTether导致无法识别设备的问题

    正文 想让手机走PC网络 xff0c 然后抓包 xff0c 于是搜索一番后安装了一个叫EasyTether的软件 还没来得及测试 xff0c 就忙着写代码去了 xff0c 重启MAC以后就发现连不上手机了 xff0c 一开始并没有怀疑是 E
  • C# 操作PDF

    Spire PDF组件概述 Spire PDF是一个专业的PDF组件 xff0c 用于在 NET应用程序中创建 xff0c 编辑 xff0c 处理和阅读PDF文档 支持丰富的PDF文档处理操作 xff0c 如PDF文档合并 拆分 转换 xf
  • 液晶显示器面板型号速查[转贴]

    原文链接 xff1a http itbbs pconline com cn topic jsp tid 61 3132291 生产厂家 显示器型号 61 面板尺寸 面板类型 xff08 面板制造商和面板型号 xff09 例 xff1a 比如
  • Node.js mm131图片批量下载爬虫1.01 增加断点续传功能

    这里的断点续传不是文件下载时的断点续传 xff0c 而是指在爬行页面时有时会遇到各种网络中断而从中断前的页面及其数据继续爬行的过程 xff0c 这个过程和断点续传原理上相似故以此命名 我的具体做法是 xff1a 在下载出现故障或是图片已经全
  • MySQL服务正在启动或停止中,请稍候片刻后再试一次【解决方案】

    相信有些小伙伴在使用数据库的过程中会经常频繁的启动和停止MySQL服务 xff0c 有时候会出现 服务正在启动或停止中 xff0c 请稍候片刻后再试一次 这样的提示 xff0c 如下图所示 于是乎想办法去解决这个问题 xff0c 但是发现连
  • if、else if、else判断语句的几个小例子

    var num 61 parseInt span class hljs string 39 10px 39 span 10 span class hljs keyword if span num gt 10 console log span
  • 微信浏览器点击系统返回,安卓返回会重载页面回到页面顶部,iOS则返回则会保留之前浏览位置的解决方法...

    后续补充 xff1a 页面css设置了height xff1a 100 xff0c 来避免使用fixed定位弹窗引起的部分机型兼容问题 xff0c 因此会在返回的时候回到页面顶部 xff0c 补充解决办法 xff1a 在弹窗出现的时候在设置
  • Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Uncaught DOMException Failed to execute 39 toDataURL 39 on 39 HTMLCanvasElement 39 Tai
  • IO Processing

    Types of IO IRP Buffer Management 首先区分一下page的内存与nonpaged的内存 xff0c 内存如果用页管理 xff0c 就难免面对被swap out的命运 xff1b 但是如果用nonpaged管理
  • Linux 7 系统如何和QQ邮箱通信

    原因 运维工作中 xff0c 当运维的网站或其它出现错误或被攻击时 xff0c 就需要Linux系统将这些提醒信息及时的通知到相应的运维人员 QQ是常用的软件 xff0c 将邮件发送到QQ邮箱可以更容易让运维人员获得提醒的信息 xff08
  • 《Programming in Lua 3》读书笔记(十八)

    日期 xff1a 2014 7 28 Part The Standard Libraries 22 The I O Library Lua的I O库提供了两种不同的文件处理模式 简单模式以I O操作是基于当前的输入文件和输出文件的 xff1