# \read: trailing spaces are removed

I'm trying to copy a (binary) file with LaTeX (mostly for the sake of it), but when I read a line, the trailing spaces are removed.

The MWE, based on this TeX.SX answer:

\edef\infile{infile}
\edef\outfile{outfile}

\openin\in=\infile%
\newwrite\out%
\immediate\openout\out\outfile%

\endlinechar-1%
\loop\unless\ifeof\in%
\immediate\write\out{\l}%
\message{copied line : \l}
\repeat%
\immediate\closeout\out%
\closein\in%
\endlinechar13%

\documentclass{article}
\begin{document}
\end{document}


The infile file consists of a single line, and has three trailing spaces:

$cat infile abc def$ tr ' ' '_' < infile
abc___def___


The outfile file, after running the above code, lacks these spaces:

$latex copy.tex ...$ cat outfile
abc   def
\$ tr ' ' '_' < outfile
abc___def


Surely there is a way to achieve that, by changing some catcodes I guess, but I tried adding some \catcode =11 (with a backtick) or \catcode = 9, but the trailing spaces were still absent from outfile.

-

The TeXbook, page 46 (third double dangerous bend):

TeX deletes any ⟨space⟩ characters (number 32) that occur at the right end of an input line. Then it inserts a ⟨return⟩ character (number 13) at the right end of the line, except that it places nothing additional at the end of a line that you inserted with ‘I’ during error recovery. Note that ⟨return⟩ is considered to be an actual character that is part of the line; you can obtain special effects by changing its catcode.

However on page 48 one finds

The special character inserted at the end of each line needn’t be ⟨return⟩; TeX actually inserts the current value of an integer parameter called \endlinechar, which normally equals 13 but it can be changed like any other parameter. If the value of \endlinechar is negative or greater than 255, no character is appended, and the effect is as if every line ends with % (i.e., with a comment character).

So you're out of luck, it seems. The space characters are removed independently of their category code.

-
Ok, too bad for plain TeX/LaTeX then. Is there some hope in reading with \pdffiledump under pdf(la)tex (this answer's third comment), and writing with the code in this answer, or using the lua extensions of lualatex ? –  Georges Dupéron Sep 7 '12 at 22:23
@GeorgesDupéron Maybe using input and output from Lua. The "space gobbling" depends on the way TeX reads its input. –  egreg Sep 7 '12 at 22:39

## Reading binary files

As already explained by egreg, spaces are lost at the end of line and also the end of line marker is unknown, because it is replaced by TeX, configured by \endlinechar.

In pdfTeX \pdffiledump can be used to read binary files:

\pdfunescapehex{\pdffiledump offset 0 length \pdffilesize{test.file}{test.file}}


or with support for LuaTeX:

\usepackage{pdftexcmds}% or \input pdftexcmds.sty\relax
\makeatletter % or \catcode\@=11\relax
\pdf@unescapehex{\pdf@filedump{0}{\pdf@filesize{test.file}}{test.file}}


## Writing binary files

• Depending on the TeX compiler and option settings, the written output might be different. Bytes could be replaced or output in ^^-notation.

• Only lines can be written. At least the last byte(s) of the file is/are an end of line marker depending on the TeX compiler and operating system.

Thus binary files can only be written by LuaTeX using Lua functions.

-
Thanks! Sorry I can't accept two answers :) . I think your first code (for \pdfunescapehex) lacks a }` by the way. –  Georges Dupéron Sep 8 '12 at 11:38
@GeorgesDupéron Fixed. –  Heiko Oberdiek Sep 8 '12 at 12:16