Using counters has some advantages in terms of logical meaning. It also shows improved robustness in some cases: there are places where the fact that counters are terminated properly is important. For example, try
\documentclass{article}
\begin{document}
\newcounter{demo}
\setcounter{demo}{10}
\newcounter{minnumber}
\setcounter{minnumber}{1}
\ifnum\value{demo}>\value{minnumber}11 correct\else oops\fi
\end{document}
versus
\documentclass{article}
\begin{document}
\newcommand*\demo{10}
\newcommand*\minnumber{1}
\ifnum\demo>\minnumber 11 correct\else oops\fi
\end{document}
This happens because a number stored in a macro can be 'partial', and so TeX will keep looking for the end of the number after the macro. This does not happen with counters, which TeX considers as 'complete'.
One thing to watch is that LaTeX counters are always set globally:
\documentclass{article}
\begin{document}
\newcounter{demo}
\begingroup
\setcounter{demo}{10}
\endgroup
\the\value{demo}
\end{document}
This effect also means that the performance (speed of execution) with counters may be better than with macros.
If you want a local value, either use a macro or use the plain TeX count register type:
\documentclass{article}
\begin{document}
\newcount\demo
\begingroup
\demo10\relax
\endgroup
\the\demo
\end{document}
(TeX count registers have a different syntax to LaTeX counters, as you can see.)
An approach without external packages can be as follows:
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.dat}
001001=aaaaaaaa
001002=bbbbbbbb
001002=cccccccc
002001=dddddddd
002002=mmmmmmmm
002003=jjjjjjjj
003001=uuuuuuuu
003002=iiiiiiii
003003=vvvvvvvv
\end{filecontents*}
\makeatletter
\newread\nina@read
\newcommand{\grabdata}[1]{%
\begingroup\endlinechar=\m@ne
\openin\nina@read=#1\relax
\loop\ifeof\nina@read\else
\read\nina@read to \@tempa
\nina@convert
\repeat
\closein\nina@read
\endgroup}
\def\nina@convert{%
\if\relax\detokenize\expandafter{\@tempa}\relax\else
\expandafter\nina@convert@i\@tempa\relax
\fi}
\def\nina@convert@i#1=#2\relax{%
\global\@namedef{nina@data@#1}{#2}}
\newcommand{\numentry}[1]{\@nameuse{nina@data@#1}}
\makeatother
\grabdata{\jobname.dat}
\begin{document}
\numentry{001001}
\numentry{001002}
\numentry{001003}
\numentry{002001}
\numentry{002002}
\numentry{002003}
\numentry{003001}
\numentry{003002}
\numentry{003003}
\end{document}
I've used \jobname.dat
as the file name just not to clobber my existing files.
If the data file is named foo.xyz
you'll use
\grabdata{foo.xyz}
and then the data will be available in the form
\numentry{001001}
The data file is read line by line and each line is split at the =
token to get the key and the value. So if the line is
001001=aaaaaaaa
we essentially do
\@namedef{nina@data@001001}{aaaaaaaa}
(globally, as we use \endlinechar=-1
to avoid spurious spaces and get rid of empty lines).
Best Answer
if you want to allow all numbers then use: