# How to read a file with luatex

I tried to read a file with lua and set the content as normal text in my document, but I didn't worked it out. Here my code:

\documentclass{scrartcl}
\usepackage{luatextra}
\usepackage{filecontents}

\begin{filecontents}{testdata.dat}
A  B
1.0 20
1.1 21
1.2 22
\end{filecontents}

\begin{luacode}
file = io.open("testdata.dat", "r")
print(text)
return tex.print(text)
end
\end{luacode}

\begin{document}
\end{document}


But nothing is printed to the document although lua diplays the content of the file in the terminal.

-
That might be related to special characters in testdata.dat. The filecontents package seems to add a few lines at the beginning. Have you tried to disable any further interpretation in tex.print? This can be achieved by using tex.print(-2, text). –  Alexander Feb 12 '13 at 10:01
Yes I tried this, but then it messes up the linebreaks and replaces them with the \Omega letter. –  Reza Feb 12 '13 at 10:10
In your MWE, use a filecontents* environment (note the star!) and the result will be good. –  Paul Gaborit Feb 12 '13 at 10:21
@Reza Would it be correct to assume that you'll want to do further processing on the data here? Will that be in Lua or in TeX (as the line-end business will be important only in the second case).? –  Joseph Wright Feb 12 '13 at 10:30
@JosephWright Yes that's correct, I want to pass it to a pgfplotstable, like this I can perhaps circumvent escaping every tex character, like underscore etc... –  Reza Feb 12 '13 at 13:06

Edit: a short version of readtxt() function.

\begin{luacode*}
file = io.open("testdata.dat", "r")
end
\end{luacode*}


First proposition: a solution consists to store lines in a table and to "tex.print" the lines one by one (each argument of tex.print is a single line of TeX).

\documentclass{scrartcl}
\usepackage{luatextra}
\usepackage{filecontents}

\begin{filecontents}{testdata.dat}
A  B
1.0 20
1.1 21
1.2 22
\end{filecontents}

\begin{luacode}
file = io.open("testdata.dat", "r")
for line in file:lines() do
print(line)
tex.print(line)
end
end
\end{luacode}

\begin{document}
\end{document}

-
Great solution. IMO even better: for line in file:lines() do tex.print(line) end - no need for the extra variable and perfectly clear. –  topskip Feb 12 '13 at 11:34
@topskip Thanks. I edited my answer... –  Paul Gaborit Feb 12 '13 at 16:27

io.lines also closes the file and tex.sprint writes a new line in the output for every call. The reason why the %-lines are ignored by TeX automatically

\documentclass[a5paper]{article}
\usepackage{luacode,fancyvrb}
\pagestyle{empty}
\begin{filecontents}{testdata.dat}
A  B
1.0 20
1.1 21
1.2 22
\end{filecontents}

\begin{luacode*}
suffix = suffix or ""
for line in io.lines(filename) do tex.sprint(line..suffix) end
end
\end{luacode*}

\begin{document}
\VerbatimInput[frame=single]{testdata.dat}

\end{document}


-
This is the right way to implement readtxt for this qn. Minor tweak: suffix = suffix or "" is the idiomatic way to define optional parameters in Lua. –  Charles Stewart Feb 14 '13 at 9:23
@CharlesStewart: you are right, I edited the code! –  Herbert Feb 14 '13 at 11:09

The file being written by filecontents looks like this:

%% LaTeX2e file testdata.dat'
%% generated by the filecontents' environment
%% from source luareadfile' on 2013/02/12.
%%
A  B
1.0 20
1.1 21
1.2 22


When lua reads that in to the string, it does no processing. If TeX were to read that in, it would ignore the comment lines since everything from a % to a newline gets eaten up. Moreover, TeX would translate the newlines to space characters (and translate any double newlines to \par tokens).

The file then gets inserted into the TeX stream via tex.print. This, it would appear, is inserted as if the input parser has already done its job. So TeX assumes that double newlines have already been replaced by \pars and treats a newline character as simply a space token. However, it still sees the % character and is prepared to deal with it by ignoring anything after it up to a newline. But there are no newlines, so TeX keeps discarding stuff until it is stopped (at the end of the tex.print).

I don't know if it is possible to fix this "properly" by getting the new lines to be interpreted correctly, but if you have control over the file contents (as you appear to here) you could get lua to strip out the comments first using a simple pattern match before presenting the data to TeX.

\documentclass{scrartcl}
%\url{http://tex.stackexchange.com/q/97822/86}
\usepackage{luatextra}
\usepackage{filecontents}

\begin{filecontents}{testdata.dat}
A  B
1.0 20
1.1 21
1.2 22
\end{filecontents}

\begin{luacode}
file = io.open("testdata.dat", "r")
clean = string.gsub(text,'%%[^\string\n]*',"")
print(clean)
return tex.print(clean)
end
\end{luacode}

\begin{document}
\end{document}


Notice the \string! That's because your lua code is embedded in your document. It's usually a good idea to avoid that by having the lua code in a separate file.

This produces:

Reading in text: A B 1.0 20 1.1 21 1.2 22 Finished reading in text.

-

Another (besides @AndrewStacey's solution) possibility is to use string.gmatch() and insert the file line by line:

\documentclass{scrartcl}
\usepackage{luatextra}
\usepackage{filecontents}

\begin{filecontents}{testdata.dat}
A  B
1.0 20
1.1 21
1.2 22
\end{filecontents}

\begin{luacode*}
file = io.open("testdata.dat", "r")
file:close()
for x in string.gmatch(text,"[^\n]+") do
tex.print(x)
end
end
\end{luacode*}

\begin{document}

tex.print(-2,text)
`