我有一个问题。我想要:
- 构建一个电子工具箱列表
- 将此列表保存在临时文件中
- 在下次运行时从此文件中读取此列表
- 使用此文件。
出于某种原因,我看不到解决方案。 这是我的实际代码。
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
% The list
\def\a{}
\listadd{\a}{a}
\listadd{\a}{b}
% Print the list from the tex code
\begin{itemize}
\renewcommand*{\do}[1]{\item #1}
\dolistloop{\a}
\end{itemize}
\a
% Write the list in an outfile
\newwrite\outf
\openout\outf=list.txt
\write\outf{\a}
\closeout\outf
% Read the list from this file
\newread\inf
\openin\inf=list.txt
\read\inf to \b
\closein\inf
\b
% Print the list from the file
\begin{itemize}
\renewcommand*{\do}[1]{\item #1}
\dolistloop{\b}
\end{itemize}
\end{document}
在 etoolbox 的文档中,据说内部列表只是一个以 | 作为分隔符的宏。在我的输出文件中,我有 a|b。那么问题是什么?
答案1
您需要使用 关闭文件,\immediate
否则操作将在下次发送时延迟。同样,使用 写入\immediate
。
但这并不是唯一需要采取的预防措施。在文档第 24 页的脚注中,etoolbox
您会发现列表分隔符|
的类别代码为 3。因此
\documentclass{article}
\newwrite\outf
\newread\inf
\usepackage{etoolbox}
\begin{document}
% The list
\def\a{}
\listadd{\a}{a}
\listadd{\a}{b}
% Print the list from the tex code
\begin{itemize}
\renewcommand*{\do}[1]{\item #1}
\dolistloop{\a}
\end{itemize}
% Write the list in an outfile
\immediate\openout\outf=list.txt
\immediate\write\outf{\unexpanded\expandafter{\a}}
\immediate\closeout\outf
% Read the list from this file
\openin\inf=list.txt
{\catcode`|=3 \endlinechar=-1
\global\read\inf to \b}
\closein\inf
% Print the list from the file
\begin{itemize}
\renewcommand*{\do}[1]{\item #1}
\dolistloop{\b}
\end{itemize}
\end{document}
字符代码和类别代码的不寻常组合是为了得到一个不应该出现在普通文档中的分隔符,这样宏就不会被(几乎)任何类型的输入所欺骗。
请注意,我已\unexpanded
按照 Joseph Wright 的建议添加了。这将防止不必要的命令扩展\edef
(\write
例如,所有字体更改命令)。
更安全的版本是在写入时解构列表,并在读回时重建列表。这不依赖于分隔符的任何特殊性。我们只需在列表项周围添加一对额外的括号,这些括号将在重建列表时被剥离。
\documentclass{article}
\usepackage{etoolbox}
\newwrite\outf
\newread\inf
\newcommand\readlistadd[1]{\listadd\templist{#1}}
\begin{document}
% The list
\def\a{}
\listadd{\a}{a}
\listadd{\a}{b}
% Print the list from the tex code
\begin{itemize}
\renewcommand*{\do}[1]{\item #1}
\dolistloop{\a}
\end{itemize}
% Write the list in an outfile
\immediate\openout\outf=list.txt
\renewcommand\do[1]{\immediate\write\outf{{\unexpanded{#1}}}}
\dolistloop{\a}
\immediate\closeout\outf
% Read the list from this file
\openin\inf=list.txt
{\endlinechar=-1
\def\templist{}
\everyeof{}
\loop\unless\ifeof\inf
\read\inf to \temp
\ifx\temp\empty\else
\expandafter\readlistadd\temp
\fi
\repeat
\global\let\b\templist
}
\closein\inf
% Print the list from the file
\begin{itemize}
\renewcommand*{\do}[1]{\item #1}
\dolistloop{\b}
\end{itemize}
\end{document}