lua文件读取注意事项

本文介绍了一种Lua语言下的CSV文件读取方法,并实现了基于字段的排序功能。该方法适用于UTF-8编码且含有特定格式头部的CSV文件,通过表格形式存储数据,并提供了获取升序、降序排序后的ID列表的功能。
--[[
文件功能:读取CSV文件到table中,从返回的table中获取CSV的字段。
date:2013.7.18
author:JesseCen
CSV文件的规则:
         1.字符编码为UTF-8,否则不能正确处理中文字符。
         2.首行是中文描述字段名称,第二行是代码中使用的字段名称。
         3.文本第二行开始,所有的字段都要以英文逗号分隔,行最后可以不用逗号字符分隔(字段之间可以允许有多余的空格)。
         4.如果文本中需要输入","号,那么用"\,"即可(多于一个逗号还会有bug)。
访问规则:
       id关键字都要用字符串作为访问下标,例如:
       local infoTag=GameData.PlayerAnimatInfo["100110"].StartHitFrame
排序功能使用规则:
       返回按照参数2进行升序降序排列的key列表;传参1是read函数返回的表,参数2是依据该字段排序的字符串名。
       例如:local tSkillID = LuaCSVFile:getKeyTableDESC(GameData.skillBaseEffect,"skillLevel")
遇到问题:1.需要截取要读取的文件大小,否则末行因为越界而末尾乱码。
          2.lua 不能频繁的进行字符串substr操作,否则lua虚拟机频繁的申请内存和回收内存会使得文件读取很慢,应该装到table里面或用游标的方式替代。

--]]
LuaCSVFile = class("LuaCSVFile")
LuaCSVFile.__index = LuaCSVFile
local function checkPlatform()
    local enter = nil
    local sharedApplication = CCApplication:sharedApplication()
    local target = sharedApplication:getTargetPlatform()
    if target == kTargetWindows then
        enter = "\n"
    else
        enter = "\r"
    end
    return enter
end


local function trim(str) --去掉空格 
    if str == nil then  
        return nil, "the string parameter is nil"  
    end  
    str = string.gsub(str, " ", "")  
    -- str = string.gsub(str,"\r","")
     return str  
end


local function trimRN(str) --linux 上去除\r换行符,读取问题多是有符号和空格的原因
    if str == nil then
        return  nil,"the string parameter is nil"
    end
   -- str = string.gsub(str, " ", "") 
    str = string.gsub(str,"\r","")
    str = string.gsub(str,"\n","")
    return str
end


--判断关键字是数字,不是数字的将其去除
local function isNumber(str)  
    if str == nil then  
        return nil
    end  
    local ch = string.sub(str, 1, 1)  
    if ch < '0' or ch > '9' then  
        return false  
    else 
        return true
    end  
end


function LuaCSVFile:read(filePath,isFont) --isFont读取界面文字,启用时传入非nil参数,最好传入true
    local enter = checkPlatform() --enter换行符
    local file = CSVFile:getInstance()
    local csvfile = file:Open(filePath)
    local cursorStart = 1 --当前的游标开始截取的位置
    if csvfile == nil then 
        CCLuaLog("csvfile" .. "error=no open file")
       return
    end
     local totalLen = file:getLength()
     csvfile = string.sub(csvfile, 1, totalLen )
    --第一行中文说明
    cursorStart = string.find(csvfile,enter) + 1
    local filetbl = {}   
    local line = ""
    local ntable = {}


    if not isFont then
        csvfile = trim(csvfile)
    end
    local endNum = string.find(csvfile,enter,cursorStart)
    line = string.sub(csvfile,cursorStart, endNum)
    line = trimRN( line )
    if line == nil then file:Close() return end
    local keyFlag = 0
    local nIndex = 0
    local nIndexPre = 1
    local tableKeyName = ""
    while true do 
        nIndex = string.find(line,",",nIndexPre)
        if nIndex == nil then
            tableKeyName = string.sub(line,nIndexPre,string.len(line))
            if tableKeyName ~= nil then
                table.insert(ntable,tableKeyName)
            end
            break
        end
        tableKeyName = string.sub(line, nIndexPre, nIndex-1)
        nIndexPre = nIndex + 1              
        if keyFlag > 0 then --去除第一个字段
            table.insert(ntable,tableKeyName)                
        end
        keyFlag = 1
    end
     --跳过行
     cursorStart = endNum + 1
    --跳过類型行
    cursorStart = string.find(csvfile,enter,cursorStart) + 1
    ---记录字段值到subTable
    local kIndex
    local kIndef
    local onceFlag = 0
    local keyValue = ""
    while true do
        startIndex = string.find(csvfile,enter,cursorStart)
        if startIndex == nil then
                break
        end  
        line = trimRN(string.sub(csvfile, cursorStart, startIndex))
        --得到key                
        kIndex = string.find(line,",")   
        if kIndex == nil then
                break
        end     
        keyValue = string.sub(line,1,kIndex-1)
        --取得各个字段值
        local subTable = {}   
        local isEscape = nil 
        local fieldValue1 = ""
        local fieldValue = ""
        local kIndefPre = 1
        line = string.sub(line,kIndex+1,string.len(line))            
        for i,v in pairs(ntable) do        
            kIndef = string.find(line,",",kIndefPre)
            if kIndef == nil then
                local fieldValue = string.sub( line, kIndefPre, string.len(line) )
                if fieldValue ~= nil then 
                    subTable[v] = fieldValue 
                end
                break
            end 
                           
            fieldValue = string.sub(line,kIndefPre,kIndef-1)
            kIndefPre = kIndef + 1
            subTable[v] = fieldValue      
        end    
       --记录到表中  
        filetbl[keyValue] = subTable
        --跳过当前读取行
        cursorStart = startIndex + 1  
    end
    file:Close() --关掉文件流,删除new出来的堆内存
    return filetbl
end




function LuaCSVFile:save(filePath,tbl)--将读取的csv得到的tbl信息存放到其它文件中
    if filePath == nil then return end
    if tbl == nil then return end
    --Open file to write
    local dfile = io.open(filePath,"w")
    if dfile == nil then return end
    dfile:write("fileName\n")
    for i,v in pairs(tbl) do
        --dfile:write(i)
        --dfile:write(v)
        dfile:write("\n")        
    end    
end    




local function reCreateNameTable(tTable) --构造一个命名的table,用于排序
     local createTable = {}
     local tempTable = {}
     local index = 1
      for i ,v in pairs(tTable) do
        if isNumber(i) then --去除末行情况
          tempTable["id"] = i
          tempTable["record"] = v
          v.id = i
          createTable[index] = tempTable --不能用tostring(index)
          tempTable = {}  --置空
          index = index +1
         end
      end
      return createTable
end


--获取升序排列的表id值
function LuaCSVFile:getKeyTableASC(tTable,sfield) --tTable是排序的表,sfield是排序的字段字符串名
    local keyTable = {}
    local reTable = reCreateNameTable(tTable)
    --排序开始
    table.sort(reTable,function(a,b)
        return (tonumber(a.record[sfield]) < tonumber(b.record[sfield]))
    end)
     --排序结束
     --
     for i, v in pairs(reTable) do
       keyTable[i] = v.id
     end


     return keyTable
 end


--获取降序排列的表id值
 function LuaCSVFile:getKeyTableDESC(tTable,sfield) 
    local keyTable = {}
    local reTable = reCreateNameTable(tTable)
    --排序开始
    table.sort(reTable,function(a,b)
      --  local x = a.record[sfield]
        return (tonumber(a.record[sfield]) > tonumber(b.record[sfield]))
    end)
     --排序结束
     --
     for i, v in pairs(reTable) do
       keyTable[i] = v.id
     end


     return keyTable
 end


--返回原始的id表
function LuaCSVFile:getKeyTable(tTable)
  local keyTable = {}
  local reTable = reCreateNameTable(tTable)


  for i,v in pairs(reTable) do
    keyTable[i] = v.id
  end


  return keyTable
end
<think>嗯,用户想要了解如何用Lua逐行读取文件的具体实现方法。从用户提供的站内引用来看,引用了几个Lua文件读写操作的例子,特别是引用[1]、[2]、[3]都提到了逐行读取的方式。用户还特意说明这些引用只是参考,真正需要的是逐行读取的示例。通过回顾之前的对话和引用,我注意到用户其实已经引用了三个Lua文件处理的代码片段,但需要更聚焦在逐行处理上。引用[2]和[3]都展示了forlineinfile:lines()这种写法,这应该就是用户需要的核心实现方式。引用[4]还提供了C语言视角的说明作为背景补充。考虑为用户组织一个清晰简洁的回答。应该包含三个关键部分:1)基础示例,使用for循环遍历文件行2)安全打开文件处理,加入assert和错误捕获3)按需定制内容处理逻辑每个方案都需要说明代码关键点,并提示文件操作结束必须关闭文件。准备在回答后用相关问题扩展学习路径,比如性能注意事项、大文件处理和行号计数等实用技巧。需要特别注意用户强调的格式要求:所有数学表达式要用$...$格式,中文回答,引文末尾加标识。会在代码示例中演示安全关闭文件的写法。</think> 以下是Lua逐行读取文件的三种常用方法及完整示例代码: ### 方法1:使用`file:lines()`迭代器(最简洁) ```lua -- 安全打开文件 local file = assert(io.open("data.txt", "r")) -- 逐行读取并处理 for line in file:lines() do print(line) -- 替换此处为自定义处理逻辑 end -- 必须关闭文件 file:close() ``` ### 方法2:使用`file:read("*l")`显式读取 ```lua local file = assert(io.open("data.txt", "r")) while true do local line = file:read("*l") -- *l表示读取一行 if not line then break end -- 读取结束时退出循环 print(line) end file:close() ``` ### 方法3:缓冲整个文件后分行处理 ```lua local file = assert(io.open("data.txt", "r")) local content = file:read("*a") -- *a读取全部内容 file:close() -- 按换行符分割 for line in content:gmatch("[^\r\n]+") do print(line) end ``` --- ### 关键说明: 1. **文件模式**:必须使用`"r"`模式打开文本文件 2. **安全打开**:`assert(io.open())`可捕获文件不存在等异常[^2] 3. **行尾处理**:Lua自动处理不同系统的换行符(`\n`或`\r\n`)[^3] 4. **资源释放**:文件操作后必须执行`file:close()`释放资源[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值