Simple CSV read and write using Lua

Update Dec 5th 2014: Fixed and updated the code.

This is a simplified Lua script to read and write CSV files. It assumes the separator character does not exist in one of the values.

I don’t know why I couldn’t find a simple code snippet to do this on the net, but sometimes it’s just faster to write it than to search for it. Hopefully this will save you that time too:

--[[
-- Example use:
file csv1.txt:

1.23,70,hello
there,9.81,102
8,1.243,test

Save the following as test.lua to test this module:
-------------------------------------
local csvfile = require "simplecsv"
local m = csvfile.read('./csv1.txt') -- read file csv1.txt to matrix m
print(m[2][3])                       -- display element in row 2 column 3 (102)
m[1][3] = 'changed'                  -- change element in row 1 column 3
m[2][3] = 123.45                     -- change element in row 2 column 3
csvfile.write('./csv2.txt', m)       -- write matrix to file csv2.txt
-------------------------------------
]]

module(..., package.seeall) 

---------------------------------------------------------------------
local function split(str, sep)
    sep = sep or ','
    fields={}
    local matchfunc = string.gmatch(str, "([^"..sep.."]+)")
    if not matchfunc then return {str} end
    for str in matchfunc do
        table.insert(fields, str)
    end
    return fields
end

---------------------------------------------------------------------
function read(path, sep, tonum)
    tonum = tonum or true
    sep = sep or ','
    local csvFile = {}
    local file = assert(io.open(path, "r"))
    for line in file:lines() do
        fields = split(line, sep)
        if tonum then -- convert numeric fields to numbers
            for i=1,#fields do
                fields[i] = tonumber(fields[i]) or fields[i]
            end
        end
        table.insert(csvFile, fields)
    end
    file:close()
    return csvFile
end

---------------------------------------------------------------------
function write(path, data, sep)
    sep = sep or ','
    local file = assert(io.open(path, "w"))
    for i=1,#data do
        for j=1,#data[i] do
            if j>1 then file:write(sep) end
            file:write(data[i][j])
        end
        file:write('n')
    end
    file:close()
end

---------------------------------------------------------------------

5 Comments

    • I’m not sure why you encountered the error but there were some errors when transferring the code to the blog post. I’ve updated, cleaned and tested the code so please try it now and let me know if you still have problems with it.

      • ———————-
        package.path = “/etc/nginx/?.lua;” .. package.path
        require “store_key_script”

        ngx.print(package.path)
        ngx.print(“::::” .. package.cpath)
        local fileData = readCSV(“key_store.txt”)
        ngx.print(fileData)

        ngx.print(“n————-“);
        writeCSV(fileData)
        —————————————

        local function split(str, sep)

        sep = sep or ‘,’
        fields={}
        local matchfunc = string.gmatch(str, “([^”..sep..”]+)”)
        if not matchfunc then return {str} end
        for str in matchfunc do
        table.insert(fields, str)
        end
        return fields
        end

        function readCSV(path, sep)
        –tonum = tonum or true
        sep = sep or ‘,’
        local csvFile = {}
        local file = assert(io.open(path, “r”))
        for line in file:lines() do
        fields = split(line, sep)

        — not using tonum now

        –if tonum then — convert numeric fields to numbers
        — for i=1,#fields do
        — fields[i] = tonumber(fields[i]) or fields[i]
        — end
        –end
        table.insert(csvFile, fields)
        end
        file:close()
        return csvFile
        end

        function writeCSV(data, path, sep)
        — just want to print in browser only

        sep = sep or ‘,’
        –local file = assert(io.open(path, “w”))
        for i=1,#data do
        for j=1,#data[i] do
        if j>1 then ngx.print(sep) end
        ngx.print(data[i][j])
        end
        ngx.print(“n”)
        end
        –file:close()
        return true
        end
        —————————-

        If reload the server it works fine at the first attemp but gives following error in next attempts :
        storeKeyScript.lua:6: attempt to call global ‘readCSV’ (a nil value) . Help!!

  1. Pingback: A simple workflow for deep learning – Mubashir Qasim

Leave a Reply

Your email address will not be published. Required fields are marked *