What are the naming rules for \newwrites in TeX? Can \newwrites be created dynamically?

\newwrite\foo assigns the symbolic name to be equal to a write file register, so anything that is possible with \csname ...\endcsname is also possible with \newwrite or \newread, as well as with \openout,\openin, \closein, \closeout.

\newwrite itself is no TeX primitive but assigns the next free output stream number to a macro name via a \chardef, the same is true for \newread -- both stream directions are independent of each other!

In this sense, a file handle is nothing more than a macro expanding to a number, this way \immediate\write6 etc. would be possible too. (or think of writing to the shell with \immediate\write18 (given that shell-escape is enabled)).

If there's another macro inside the \csname...\endcsname statement, use an \expandafter.

The point is now: How feasible is this approach? It can be quite tedious to repeat the \csname ... \endcsname usage all the while!

Here is a similar code from the \@starttoc command in latex.ltx:

\def\@starttoc#1{%
  \begingroup
    \makeatletter
    \@input{\jobname.#1}%
    \if@filesw
      \expandafter\newwrite\csname tf@#1\endcsname
      \immediate\openout \csname tf@#1\endcsname \jobname.#1\relax
    \fi
    \@nobreakfalse
  \endgroup}

It can be seen that the file handle of the toc - file is generated on the fly over and over again (for each \@starttoc - call)

Some points to consider:

  • My solution is only correct if opening, writing and closing is within the \foreach cycle, since this establishes a group, so the filename handle macro name isn't available outside of the \foreach - cycle. However, this procedure is not recommended.

  • Is it really necessary to use a new handle for each file? No, not really, since apparently the file handle is generated, the file opened etc. and the 'active' file is determined by the \foreach loop variable \langcode, so it's not easily possible to write to more than one file(handle) at the 'same' time.


\documentclass{article}
\usepackage{fontspec}% xelatex
\usepackage{tikz}% foreach
\usepackage{morewrites}% unnecessary for this example, but useful in practice to exceed 16-write limit in TeX


\def\writelangouts{%
  \foreach \langcode in {da,de,en} {% from tikz package
    \expandafter\newwrite\csname filehandle-\langcode\endcsname
    \immediate\openout\csname filehandle-\langcode\endcsname=\jobname-semantically_useful_suffix_\langcode.txt
    \immediate\closeout\csname filehandle-\langcode\endcsname
  }%
}%

    \def\otherwritelangouts{%
  \foreach \langcode in {da,de,en} {% from tikz package
    \def\fhandle{\csname filehandle-\langcode\endcsname}
    \newwrite\fhandle%
    \immediate\openout\fhandle=\jobname-semantically_useful_suffix_\langcode.txt
    \immediate\closeout\fhandle
  }%
}%


\AtEndDocument{\writelangouts}

\begin{document}
\jobname
\end{document}

Assuming the file above is called fhandle.tex, the .log - file shows that following file handles are generated (at the end of the document, since \writelangouts is used in \AtEndDocument)

ABD: EveryShipout initializing macros
\AtBeginShipoutBox=\box53
\filehandle-da=\write5
\openout4 = `fhandle-semantically_useful_suffix_da.txt'.

\filehandle-de=\write6
\openout4 = `fhandle-semantically_useful_suffix_de.txt'.

\filehandle-en=\write7
\openout4 = `fhandle-semantically_useful_suffix_en.txt'.

If your task is to open a file, write on it and close it all in the same cycle of the \foreach loop, you need just one file handle.

\documentclass{article}

\usepackage{tikz}% foreach

\newwrite\langouts
\newcommand\writelangouts{%
  \foreach \langcode in {da,de,en} {% from tikz package
    \immediate\openout\langouts=\jobname-\langcode.txt
    \immediate\write\langouts{This is \langcode}
    \immediate\closeout\langouts
  }%
} 
\AtEndDocument{\writelangouts}

\begin{document}
\jobname
\end{document}

The contents of the written files

test-da.txt

This is da

test-de.txt

This is de

test-en.txt

This is en