如何从外部文件逐个读取字符,修改它,并将其保存回另一个外部文件?

如何从外部文件逐个读取字符,修改它,并将其保存回另一个外部文件?

本题的目的是学习如何逐个字符地读取一行字符,进行修改并保存到另一个文件中。

为了简单起见,我们以一个简单的应用程序为例,它使用众所周知的简单算法“移位密码”加密外部文本文件。我只能给你一个框架,如下所示,其余的我都不知道。

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{plain.txt}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
\end{filecontents*}

% shift parameter, 
% positive value moves forward (for example, 1 makes A get shifted to B),
% negative value moves backward (for example, -1 makes B get shifted to A).
\def\offset{13}

\newread\reader
\newwrite\writer

\begin{document}
\openin\reader=plain.txt
\immediate\openout\writer=encrypted.txt
    \loop
        \read\reader to \data
        \unless\ifeof\reader
            \immediate\write\writer{Do something here}
    \repeat
\immediate\closeout\writer
\closein\reader
\end{document}

我想了解的有趣的部分:

  • 如何从外部文件中获取的单行逐个读取一个字符。
  • 如何修改单个字符。
  • 如何知道从外部文件中提取的单行字符数。

请使用最简单的方法,以便新手(像我)可以轻松消化代码。

答案1

最简单的方法是设置大写表来进行翻译。

该文件进行两次编码以确认您回到开始的地方(除了空格规范化)

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{plain.txt}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
\end{filecontents*}

% shift parameter, 
% positive value moves forward (for example, 1 makes A get shifted to B),
% negative value moves backward (for example, -1 makes B get shifted to A).
\def\offset{13}

\newread\reader
\newwrite\writer

\def\wrot#1{%
\uppercase{\immediate\write\writer{#1}}}

\begin{document}
\makeatletter


{
\count@`a
\loop
\uccode\count@=\numexpr\count@+\offset\relax
\uccode\numexpr\count@+\offset\relax=\count@
\advance\count@\@ne
\ifnum\count@<`n
\repeat

\count@`A
\loop
\uccode\count@=\numexpr\count@+\offset\relax
\uccode\numexpr\count@+\offset\relax=\count@
\advance\count@\@ne
\ifnum\count@<`N
\repeat

\openin\reader=plain.txt
\immediate\openout\writer=encrypted.txt
    \loop
        \read\reader to \data
        \unless\ifeof\reader
            \expandafter\wrot\expandafter{\data}
    \repeat
\immediate\closeout\writer
\closein\reader

\openin\reader=encrypted.txt
\immediate\openout\writer=reencrypted.txt
    \loop
        \read\reader to \data
        \unless\ifeof\reader
            \expandafter\wrot\expandafter{\data}
    \repeat
\immediate\closeout\writer
\closein\reader


}

\section{plain.txt}
\input{plain.txt}

\section{encrypted.txt}
\input{encrypted.txt}

\section{reencrypted.txt}
\input{reencrypted.txt}

\end{document}

在此处输入图片描述

答案2

这应该允许所有 ASCII 可打印字符。

\begin{filecontents*}{plain.txt}
u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
\end{filecontents*}

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\int_gzero_new:N \g_karl_offset_int
\ior_new:N \l_karl_input_stream
\iow_new:N \l_karl_output_stream
\seq_new:N \l__karl_input_seq
\tl_new:N \l__karl_input_tl
\tl_new:N \l__karl_temp_tl
\tl_const:Nn \c_karl_space_tl { ~ }

\NewDocumentCommand{\cypher}{omm}
 {% #1 = shift #2 = input file, #3 = output file
  \IfValueT{#1}{ \int_gset:Nn \g_karl_offset_int { #1 } }
  \ior_open:Nn \l_karl_input_stream { #2 }
  \iow_open:Nn \l_karl_output_stream { #3 }
  \ior_str_map_inline:Nn \l_karl_input_stream
   {
    \tl_set:Nn \l__karl_input_tl { ##1 }
    \tl_replace_all:Nnn \l__karl_input_tl { ~ } { \c_karl_space_tl }
    \karl_write:V \l__karl_input_tl
   }
  \ior_close:N \l_karl_input_stream
  \iow_close:N \l_karl_output_stream
 }

\cs_new_protected:Npn \karl_write:n #1
 {
  \tl_clear:N \l__karl_temp_tl
  \tl_map_inline:nn { #1 } { \karl_shift:n { ##1 } }
  \iow_now:NV \l_karl_output_stream \l__karl_temp_tl
 }

\cs_generate_variant:Nn \karl_write:n { V }
\cs_generate_variant:Nn \iow_now:Nn { NV }

\cs_new_protected:Npn \karl_shift:n #1
 {
  \group_begin:
  \token_if_eq_meaning:NNTF #1 \c_karl_space_tl
   {
    \char_set_lccode:nn { `~ } { \g_karl_offset_int + 32 }
    \tl_to_lowercase:n { \group_end: \tl_put_right:Nn \l__karl_temp_tl { ~ } }
   }
   {
    \int_compare:nTF { `#1 + \g_karl_offset_int > 126 }
     { \char_set_lccode:nn { `#1 } { `#1 + \g_karl_offset_int - 126 + 32 } }
     {
      \int_compare:nTF { `#1 + \g_karl_offset_int < 32 }
       { \char_set_lccode:nn { `#1 } { `#1 + \g_karl_offset_int + 126 - 32 } }
       { \char_set_lccode:nn { `#1 } { `#1 + \g_karl_offset_int } }
     }
    \tl_to_lowercase:n { \group_end: \tl_put_right:Nn \l__karl_temp_tl { #1 } }
   }
 }
\ExplSyntaxOff

\cypher[13]{plain.txt}{thirteen.txt}

\cypher[-13]{thirteen.txt}{plain13.txt}

\cypher[15]{plain.txt}{fifteen.txt}

\cypher[-15]{fifteen.txt}{plain15.txt}

\stop

plain.txt

u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.

thirteen.txt

$3FMMk*J.**,
Xn!y4"-"#$qr{#"-q|-{|#-pn!r-no|$#-qn"uv{t-}n##r!{";
Xn!y4"-"#$qr{#"-q|-{|#-pn!r-no|$#-n!!|&-#v}";
Xn!y4"-"#$qr{#"9-o(-#ur-&n(9-q|-{|#-x{|&-&un#-n-#!n{"s|!zn#v|{-zn#!v'-v";

plain13.txt

u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.

fifteen.txt

&5HOOm,L0,,.
Zp#{6$/$%&st}%$/s~/}~%/rp#t/pq~&%/sp$wx}v/!p%%t#}$=
Zp#{6$/$%&st}%$/s~/}~%/rp#t/pq~&%/p##~(/%x!$=
Zp#{6$/$%&st}%$;/q*/%wt/(p*;/s~/}~%/z}~(/(wp%/p/%#p}$u~#|p%x~}/|p%#x)/x$=

plain15.txt

u&9@@^{=!{{}
Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.

答案3

虽然我完全赞成使用 LaTeX 作为制作精美书籍和文档的工具,但这个问题只是要求使用一种更适合该问题的编程语言来回答。

这是用 Python 实现的。它非常冗长,但我认为几乎所有有编程知识的人,即使从未见过一行 Python 代码,也能理解并在一定程度上修改以下代码:

import string

filecontents = """Karl's students do not care about dashing patterns.
Karl's students do not care about arrow tips.
Karl's students, by the way, do not know what a transformation matrix is.
"""

f = open('plain.txt', 'w')
f.write(filecontents)
f.close()

def shift(char, offset):
    if char in string.lowercase:
        shifted_index = string.lowercase.index(char) + offset
        shifted_char = string.lowercase[shifted_index % len(string.lowercase)]
    elif char in string.uppercase:
        shifted_index = string.uppercase.index(char) + offset
        shifted_char = string.uppercase[shifted_index % len(string.uppercase)]
    else:
        # do nothing for special characters, otherwise we end up with non-printable
        shifted_char = char
    return shifted_char

def read_process_save(filename, offset):
    input = open('plain.txt', 'r')
    output = open('plain_shift.txt','w')
    while True:
        char = input.read(1)
        if char: 
            shifted = shift(char, offset)
            output.write(shifted)
        else:
            break
    input.close()
    output.close()

offset = 13
read_process_save('plain.txt', offset)

plain_shifted.txt生成包含以下内容的文件:

Xney'f fghqragf qb abg pner nobhg qnfuvat cnggreaf.
Xney'f fghqragf qb abg pner nobhg neebj gvcf.
Xney'f fghqragf, ol gur jnl, qb abg xabj jung n genafsbezngvba zngevk vf.

如果我们更加 Pythonic 并使用“包含电池”座右铭,标准库甚至提供 rot13 编码:

from codecs import getencoder
encoder = getencoder('rot-13')
rot13string = encoder(mystring)[0]

相关内容