Update Dec 5th 2014: Fixed and updated the code.
Update Mar 9th 2017: Updated the code to handle null values in CSV.
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:
--[[ ------------------------------- Save this file as simplecsv.lua ------------------------------- Example use: Suppose file csv1.txt is: 1.23,70,hello there,9.81,102 x,y,,z 8,1.243,test Then the following ------------------------------------- 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 ------------------------------------- will produce file csv2.txt with the contents: 1.23,70,changed there,9.81,123.45 x,y,,z 8,1.243,test the read method takes 4 parameters: path: the path of the CSV file to read - mandatory sep: the separator character of the fields. Optionsl, defaults to ',' tonum: whether to convert fields to numbers if possible. Optional. Defaults to true null: what value should null fields get. Optional. defaults to '' ]] module(..., package.seeall) --------------------------------------------------------------------- function string:split(sSeparator, nMax, bRegexp) if sSeparator == '' then sSeparator = ',' end if nMax and nMax < 1 then nMax = nil end local aRecord = {} if self:len() > 0 then local bPlain = not bRegexp nMax = nMax or -1 local nField, nStart = 1, 1 local nFirst,nLast = self:find(sSeparator, nStart, bPlain) while nFirst and nMax ~= 0 do aRecord[nField] = self:sub(nStart, nFirst-1) nField = nField+1 nStart = nLast+1 nFirst,nLast = self:find(sSeparator, nStart, bPlain) nMax = nMax-1 end aRecord[nField] = self:sub(nStart) end return aRecord end --------------------------------------------------------------------- function read(path, sep, tonum, null) tonum = tonum or true sep = sep or ',' null = null or '' local csvFile = {} local file = assert(io.open(path, "r")) for line in file:lines() do fields = line:split(sep) if tonum then -- convert numeric fields to numbers for i=1,#fields do local field = fields[i] if field == '' then field = null end fields[i] = tonumber(field) or field 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 ---------------------------------------------------------------------