\documentclass{article}
\makeatletter
\def\a{[expanded a]}
% Broken version: hash not in horiz mode.
\def\allowhashBROKEN#1{
  {\toks@{#1}\the\toks@}
}

% stack exchange query: Duplicated by \scantokens
\def\allowhashBAD#1{
  {\toks@{#1}\catcode`\#11\relax\scantokens\expandafter{\the\toks@}}%
}
% David Carlisle's version: Never actually creates T_PARAM!
\def\allowhashDC{%%%%
    \bgroup\catcode35=11\relax\afterassignment\egroup\gdef\foo}%

\newwrite\file
\def\readnext{
  \ifeof\file
    \closein\file
     Full Contents:``\expandafter\detokenize\expandafter{\contents}''\\
  \else
     \read\file to \aline
     Line:``\expandafter\detokenize\expandafter{\aline}''\\
     \expandafter\g@addto@macro\expandafter\contents\expandafter{\aline}
     \readnext
  \fi}

\def\readfile#1{
  \def\contents{}%
  Reading file #1:\\
 \openin\file = #1
  \readnext}

\makeatother
\begin{document}
\section{Testing duplication of \#}
\message{message: Two hashes: #, not one; \a.}

\detokenize{detokenize: Two hashes: #, not one; \a.}

\allowhashBAD{scantokens: two hashes: #, not one; \a.}

\allowhashDC{Deferred tokenize: One hash: #, not two; \a.}\foo

\section{In definitions}
\def\foo{Also two hashes##, not one}
\expandafter\detokenize\expandafter{\foo}

\edef\fufu{\expandafter\detokenize\expandafter{\foo}}

\fufu

\section{File io}
\readfile{badchars.tex}

\end{document}