`\write` schreibt sein sogenanntes *balanced text*-Argument expandiert in die über `<handler>` angegebene Datei, sobald die aktuelle Seite ausgegeben wird. (Die Ausgabe der Seite war ursprünglich gleichbedeutend mit dem Schreiben in die DVI-Datei). Der Vorteil dieses Vorgehens ist, dass beispielsweise `\thepage` bereits den Wert der aktuell ausgegeben Seite enthält.
`\immediate\write` wiederum schreibt das expandierte Argument sofort in die über `<handler>` angegebene Datei. LaTeX verwendet dies beispielsweise, um in die Haupt-`aux`-Datei bei `\include` Ladeanweisungen für die Unter-`aux`-Dateien zu schreiben.
Beispiel (`\write`):
\documentclass{article}
\usepackage{blindtext}
\newcounter{test}
\makeatletter
\newcommand*{\dowrite}[1]{%
\stepcounter{test}%
\write\@mainaux{\string\def\string\testpage{\thetest: #1}}%
}
\makeatother
\begin{document}
\dowrite{\thepage}
\blindtext[1]
\dowrite{\thepage}
\blindtext[4]
\dowrite{\thepage}
\end{document}
schreibt in die `aux`-Datei:
<pre>
`\def\testpage{3: 1}
\def\testpage{3: 1}
\def\testpage{3: 2}`
</pre>
Die Erklärung dafür ist einfach: Der Zähler `test` wird bei jedem Aufruf von `\dowrite` um eins erhöht. Geschrieben wird aber tatsächlich erst am Ende des Dokuments, weil erst dann LaTeX erkennt, dass nicht mehr alles auf die erste Seite passt. Daher ist beim Schreiben der Zähler bereits `test` bereits 3. Der Zähler `page` wird erst beim Schreiben einer Seite erhöht. Daher ist er beim Schreiben der ersten Seite tatsächlich 1 und beim Schreiben der zweiten Seite tatsächlich 2.
Jetzt mit `\immediate\write`:
\documentclass{article}
\usepackage{blindtext}
\newcounter{test}
\makeatletter
\newcommand*{\dowrite}[1]{%
\stepcounter{test}%
\immediate\write\@mainaux{\string\def\string\testpage{\thetest: #1}}%
}
\makeatother
\begin{document}
\dowrite{\thepage}
\blindtext[1]
\dowrite{\thepage}
\blindtext[4]
\dowrite{\thepage}
\end{document}
Hier lauten die Einträge in die `aux`-Datei:
<pre>
`\def\testpage{1: 1}
\def\testpage{2: 1}
\def\testpage{3: 1}`
</pre>
Nun haben wir quasi den umgekehrten Fall. Da die Einträge direkt bei der Ausführung von `\dowrite` geschrieben werden, befinden wir uns zu diesem Zeitpunkt noch immer auf Seite 1 und es wird der jeweils aktuelle Wert von `test` geschrieben. Die letzte `\dowrite`-Anweisung wird ebenfalls noch auf Seite 1 verarbeitet, weil erst beim impliziten Absatz von `\end{document}` erkannt wird, dass ein Teil des Materials der letzten `\blindtext`-Anweisung auf einer neuen Seite ausgegeben werden muss.
`\protected@write` verwendet intern ebenfalls `\write`. Allerdings unterscheidet es sich davon in zwei Punkten. Zunächst einmal definiert es `\thepage` so um, dass es bei der Expansion quasi zu sich selbst expandiert, und `\protect` so, dass es selbst erhalten bleibt und die Anweisung unmittelbar danach ebenfalls nicht expandiert wird. Dann führt es das nächste Argument aus und expandiert das übernächste mit `\edef`. Das so expandierte Argument wird dann wieder mit `\write` in die Datei geschrieben. In erster Linie bedeutet das, dass man bei Verwendung von `\protected@write` mit `\protect` arbeiten kann, um Expansionen zu verhindern, es ansonsten aber von `\thepage` abgesehen wie `\immediate\write` arbeitet:
\documentclass{article}
\usepackage{blindtext}
\newcounter{test}
\makeatletter
\newcommand*{\dowrite}[1]{%
\stepcounter{test}%
\protected@write\@mainaux{}{\protect\def\protect\testpage{\thetest: #1}}%
}
\makeatother
\begin{document}
\dowrite{\thepage}
\blindtext[1]
\dowrite{\thepage}
\blindtext[4]
\dowrite{\thepage}
\end{document}
Hier erhalten wird:
<pre>
`\def \testpage {1: 1}
\def \testpage {2: 1}
\def \testpage {3: 2}`
</pre>
Das ist also eine Art Mischform aus `\immediate\write` und `\write`. Die unmittelbare Expansion wird durch das erwähnte `\edef` erreicht und führt dazu, dass der bei Ausführung von `\dowrite` aktualisierte Wert von `test` geschrieben wird. Die Expansion von `\thepage` wurde durch dessen Umdefinierung innerhalb von `\protected@write` verhindert, so dass der beim Schreiben der Seite gültige Wert von `page` geschrieben wird. Die zusätzlichen Lücken nach `\def` und `\testpage` kommen übrigens daher, dass hier kein String, sondern tatsächlich das nicht expandierte Makro geschrieben wird. Vergleichbar wäre das der Verwendung von `\noexpand` statt `\string` in den vorherigen Beispielen.
Stellt sich nun die Frage, wie wir auch `\thetest` erst beim Schreiben der Seite expandieren könnten. Dafür haben wir das im obigem Beispiel noch leere, also unbenutzte Argument:
\documentclass{article}
\usepackage{blindtext}
\newcounter{test}
\makeatletter
\newcommand*{\dowrite}[1]{%
\stepcounter{test}%
\protected@write\@mainaux{\let\thetest\relax}{\protect\def\protect\testpage{\thetest: #1}}%
}
\makeatother
\begin{document}
\dowrite{\thepage}
\blindtext[1]
\dowrite{\thepage}
\blindtext[4]
\dowrite{\thepage}
\end{document}
Und schon erhalten wir wieder:
<pre>
`\def \testpage {3: 1}
\def \testpage {3: 1}
\def \testpage {3: 2}`
</pre>
Durch das `\let\thetest\relax` expandiert die Anweisung `\thetest` mit `\edef` quasi zu sich selbst und wird damit erst von `\write` beim Schreiben der Seite tatsächlich expandiert.
LaTeX selbst verwendet `\protected@write` beim Schreiben in die Hilfsdateien. Damit wird automatisch sichergestellt, dass `\thepage` das korrekte Ergebnis, also die Seitennummer der ausgegebenen Seite erhält und der Anwender zum Schutz zerbrechlicher Befehle in *moving arguments* `\protect` verwenden kann.
Das Paket [`scrlfile`](http://www.ctan.org/pkg/koma-script) definiert außerdem noch eine `\immediate`-Variante von `\protected@write`. Diese definiert `\thepage` nicht um, da es ja ohnehin unmittelbar expandiert werden muss. Außerdem definiert es innerhalb von `\BeforeClosingMainAux` die Anweisung `\protected@write` so um, dass sie die `\immediate`-Variante verwendet. Das ist notwendig, damit Anweisungen wie `\label`, `\addtocontents` oder `\addcontentsline`, die innerhalb von `\BeforeClosingMainAux` verwendet werden, tatsächlich noch etwas in die `aux`-Datei schreiben, obwohl danach keine Seite mehr ausgegeben wird (bzw. laut Spezifikation ausgegeben werden darf).