4
\documentclass{article}
\usepackage{lipsum}

\newwrite\foo
\openout\foo=foo.foo

\begin{document}

\immediate\write\foo{A}
\immediate\write\foo{B}
\lipsum
\immediate\write\foo{C}
\lipsum
\immediate\write\foo{D}

\end{document}
\closeout\foo

When compiling the above, foo.foo contains

C
D

If I remove the \immediates, it also includes A and B as expected. What causes this behavior?

1
  • 3
    \immediate\openout\foo=foo.foo Commented Jan 24 at 16:36

2 Answers 2

6

You need

\immediate\openout\foo=foo.foo

so that it is opened before the first page is shipped out and also if you want to explicitly close it you need

\closeout\foo

before \end{document} as no commands after \end{document} are executed. However the file stream will be closed cleanly if it is still open at the end of the run so \closeout is not needed unless you need to input the file during the same run.

5

You can note that the console displays

This is pdfTeX, Version 3.141592653-2.6-1.40.25 (TeX Live 2023) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./ray.tex
LaTeX2e <2023-11-01> patch level 1
L3 programming layer <2024-01-22>
(/usr/local/texlive/2023/texmf-dist/tex/latex/base/article.cls
Document Class: article 2023/05/17 v1.4n Standard LaTeX document class
(/usr/local/texlive/2023/texmf-dist/tex/latex/base/size10.clo))
(/usr/local/texlive/2023/texmf-dist/tex/latex/lipsum/lipsum.sty
(/usr/local/texlive/2023/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty
(/usr/local/texlive/2023/texmf-dist/tex/latex/l3kernel/expl3.sty
(/usr/local/texlive/2023/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)))
(/usr/local/texlive/2023/texmf-dist/tex/latex/lipsum/lipsum.ltd.tex))
No file ray.aux.
A
B
[1{/usr/local/texlive/2023/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
[2] [3] (./ray.aux) )</usr/local/texlive/2023/texmf-dist/fonts/type1/public/ams
fonts/cm/cmr10.pfb>
Output written on ray.pdf (3 pages, 27002 bytes).
Transcript written on ray.log.

which means that the file is not yet open at the time \immediate\write\foo{A} is scanned.

Every operation related to writing in files not prefixed by \immediate will be delayed at the next shipout. This includes \openout and \closeout.

So you should do \immediate\openout as well.

By the way, note that expl3 only opens write for writing immediately.

\documentclass{article}
\usepackage{lipsum}

\ExplSyntaxOn

\NewDocumentCommand{\openwritestream}{smm}
 {
  \IfBooleanT { #1 }
   {% * version also allocates
    \iow_new:c { g_ray_write_#2_iow }
   }
  \iow_open:cn { g_ray_write_#2_iow } { #3 }
 }
\NewDocumentCommand{\writestream}{smm}
 {
  \IfBooleanTF{#1}
   { \iow_now:ce }% expanded
   { \iow_now:cn }% not expanded
   { g_ray_write_#2_iow } { #3 }
 }
\NewDocumentCommand{\closewritestream}{m}
 {
  \iow_close:c { g_ray_write_#1_iow }
 }

\ExplSyntaxOff

\openwritestream*{foo}{\jobname.foo}

\newcommand{\test}{xyz}

\begin{document}

\writestream{foo}{A}
\writestream{foo}{B}
\lipsum
\writestream{foo}{C}
\lipsum
\writestream{foo}{D}
\writestream{foo}{\test}
\writestream*{foo}{\test}

\closewritestream{foo}

\end{document}

This is the contents of the ray.foo file:

A
B
C
D
\test 
xyz

Note the difference: \write always performs full expansion on the argument, whereas \writestream doesn't, unless called as \writestream*.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .