12

I have a file called assocFile.dat. The file has the following format:

0/b

1/d

2/f

3/h

I want to use this file to draw nodes (however it would be nice if this question can be answered in a general way, without having to worry about the number of values in a row).

\foreach\a/\b in {??} {
    \draw (\a,0) node{\b};
}

is there a way to open the file and process tikz commands with the content of it?

EDIT: The .tex file also writes to the file:

I've defined the following macro:

\newcommand{\writeToAssoc}[1]\newcommand{\writeToFile}{\immediate\write\assocfile{\arabic{assocCounter}/#1}\refstepcounter{assocCounter}}

after (!) writing the TikZ code I have the following sequence of commands:

\newwrite\assocfile
\immediate\openout\assocfile=assocFile.dat
\writeToAssoc{b}
\writeToAssoc{d}
\writeToAssoc{f}
\writeToAssoc{h}
\immediate\closeout\assocfile

2 Answers2

13

You can use catchfile: the command \CatchFileDef defines its first argument to expand to the contents of the file given as third argument; the third is used to apply some setup, here we tell TeX to change the end-of-line character into a comma; next we have to pass the data to TikZ in a suitable form, so we define \tempb to expand to the prolog of \foreach and in the braces we expand \tempa.

\documentclass{article}
\usepackage{catchfile,tikz}

\begin{document}

\begin{tikzpicture}
  \CatchFileDef{\tempa}{assocFile.dat}{\endlinechar=`,}
  \edef\tempb{\unexpanded{\foreach\a/\b in }{\unexpanded\expandafter{\tempa}}}
  \tempb { \draw (\a,0) node{\b}; }
\end{tikzpicture}

\end{document}

(Note: the added \unexpanded around \tempa is irrelevant in your example, but might be necessary if the \b part has arbitrary contents.)

EXAMPLE

\begin{filecontents*}{assocFile.dat}
1/-1-
2/-2-
3/-3-
4/-4-
\end{filecontents*}

\documentclass{article}
\usepackage{catchfile,tikz}

\begin{document}

\begin{tikzpicture}
  \CatchFileDef{\tempa}{assocFile.dat}{\endlinechar=`,}
  \edef\tempb{\unexpanded{\foreach\a/\b in }{\unexpanded\expandafter{\tempa}}}
  \tempb { \draw (\a,\a) node{\b}; }
\end{tikzpicture}

\end{document}

enter image description here

egreg
  • 1,121,712
  • Thanks! The program only stops after the first line? Is there a way to solve this? It seems to me that the reader actually skips the newline, because the next number is added to the text of the first node. Is there a way to check first if the file exists, and in the case it doesn't skip the commands? – willeM_ Van Onsem Mar 20 '12 at 01:08
  • @CommuSoft I don't understand: the picture compiles as the added example shows. – egreg Mar 20 '12 at 07:25
  • Well the code compiles and no runtime errors, but it only prints the first element resulting in "-1- 2" (without the quotes). So I think it doesn't respect the end-char. And reads until the next /. I'm using Linux and I know there are differences between the endline characters in Windows and Linux. A quick look at your website however shows me you are probably also running Linux :D – willeM_ Van Onsem Mar 20 '12 at 09:15
  • The file itself is generated by the LaTeX file itself (with \write) statements, another solution would be to place ,-chars instead of newlines as separators. I have searched the internet to solve this, however I haven't found a solution yet. – willeM_ Van Onsem Mar 20 '12 at 09:25
  • @CommuSoft Probably the problem is exactly in how you generate the file. Can you show how you do it? – egreg Mar 20 '12 at 12:12
  • I'm quite sure it has nothing to do with it, because I've also manually written the file, and still there result doesn't work. But I've put the command sequence into the question. – willeM_ Van Onsem Mar 21 '12 at 01:12
  • @CommuSoft The code you added is wrong; I modified it to actually do the writing and I get the expected result. – egreg Mar 21 '12 at 09:09
  • @egreg how to clear the last comma, I use this answer to "input" files – rpapa Oct 18 '15 at 18:51
  • @rpapa I think it would be better to ask a new question explaining what you want to achieve. – egreg Oct 18 '15 at 19:35
  • @WillemVanOnsem, Thanks for this. In my scenario, I was \input{}ing each of the csv entries (filenames). My workaround, instead of your other answer @egreg, was to simply make an empty file called .tex, so \intput didn't error (result is empty anyways). I post this here in case others have similar scenarios. – jessexknight Oct 13 '17 at 20:10
5

You can read the data file into a pgfplotstable and then loop over the rows by using \pgfplotstableforeachcolumnelement:

\documentclass{article}
\usepackage{pgfplotstable}
\begin{filecontents}{assocFile.dat}
0/b
1/d
2/f
3/h
\end{filecontents}

\pgfplotstableread[header=false,white space chars=/]{assocFile.dat}\datatable

\begin{document}
\begin{tikzpicture}
\pgfplotstableforeachcolumnelement{[index]0}\of\datatable\as\cell{
    \pgfplotstablegetelem{\pgfplotstablerow}{[index]1}\of\datatable
    \node at (\cell,0) {\pgfplotsretval};
}
\end{tikzpicture}
\end{document}
Jake
  • 232,450