帮助进行字节移位

发布于 2024-07-19 05:26:38 字数 1185 浏览 5 评论 0原文

我需要对文本文件进行字节移位。 我对 Perl 一无所知,但我在 Perl 中发现了一段完美工作的代码,名为 moz-byteshift.pl文档 )。 这正是我想做的,但我需要用 C# 来做。

这是 perl 文件的源代码:

#!/usr/bin/perl

# To perform a byteshift of 7
#   To decode: moz-byteshift.pl -s -7 <infile >outfile
#   To encode: moz-byteshift.pl -s  7 <infile >outfile

# To perform a byteshift of 13
#   To decode: moz-byteshift.pl -s -13 <infile >outfile
#   To encode: moz-byteshift.pl -s  13 <infile >outfile

use encoding 'latin1';
use strict;
use Getopt::Std;

use vars qw/$opt_s/;

getopts("s:");
if(!defined $opt_s) {
  die "Missing shift\n";
}

my $buffer;
while(1) {
  binmode(STDIN, ":raw");
  my $n=sysread STDIN, $buffer, 1;
  if($n == 0) {
    last;
  }
  my $byte = unpack("c", $buffer);
  $byte += 512 + $opt_s;
  $buffer = pack("c", $byte);
  binmode(STDOUT, ":raw");
  syswrite STDOUT, $buffer, 1;
}

如果有人至少可以解释 perl 脚本是如何工作的,那就太好了。 C# 中的等效示例代码会更好。 =)

感谢您的帮助。

I need to byte-shift a text file. I know absolutely nothing about perl, but I found a perfectly working piece of code in perl called moz-byteshift.pl (documentation). This does exactly what I want to do, but I need to do it in C#.

Here's the source code of the perl file:

#!/usr/bin/perl

# To perform a byteshift of 7
#   To decode: moz-byteshift.pl -s -7 <infile >outfile
#   To encode: moz-byteshift.pl -s  7 <infile >outfile

# To perform a byteshift of 13
#   To decode: moz-byteshift.pl -s -13 <infile >outfile
#   To encode: moz-byteshift.pl -s  13 <infile >outfile

use encoding 'latin1';
use strict;
use Getopt::Std;

use vars qw/$opt_s/;

getopts("s:");
if(!defined $opt_s) {
  die "Missing shift\n";
}

my $buffer;
while(1) {
  binmode(STDIN, ":raw");
  my $n=sysread STDIN, $buffer, 1;
  if($n == 0) {
    last;
  }
  my $byte = unpack("c", $buffer);
  $byte += 512 + $opt_s;
  $buffer = pack("c", $byte);
  binmode(STDOUT, ":raw");
  syswrite STDOUT, $buffer, 1;
}

If someone could at least explain how the perl script works, that would be great. Sample code of the equivalent in C# would be better. =)

Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

︶葆Ⅱㄣ 2024-07-26 05:26:38

没什么可说的。 它一次读取一个字节,将每个字节的值调整为任意值(通过 -s 标志指定),然后写出调整后的字节。 它是文本文件的 ROT-13 加密的二进制等价物。

其余的细节特定于 Perl 如何做这些事情。 getopts() 是一个处理命令行开关的函数(来自 Getopt::Std 模块)。 binmode() 将文件句柄置于原始模式,以绕过 Perl 在 I/O 期间通常执行的任何操作。 sysread() 和 syswrite() 函数用于低级流访问。 pack()和unpack()函数用于读写二进制数据; Perl 不支持本地类型。

这在 C 中重新实现是微不足道的。我建议这样做(如果需要的话从 C# 绑定到它)而不是直接移植到 C#。

There's not much to tell. It reads a file one byte at a time, adjusts the value of each byte by an arbitrary value (specified via the -s flag), and writes out the adjusted bytes. It's the binary equivalent of ROT-13 encryption of a text file.

The rest of the details are specific to how Perl does those things. getopts() is a function (from the Getopt::Std module) that processes command-line switches. binmode() puts the filehandles in raw mode to bypass any of the magic that Perl normally does during I/O. The sysread() and syswrite() functions are used for low-level stream access. The pack() and unpack() functions are used to read and write binary data; Perl doesn't do native types.

This would be trivial to re-implement in C. I'd recommend doing that (and binding to it from C# if need be) rather than porting to C# directly.

弥繁 2024-07-26 05:26:38

代码的作用是这样的:从标准输入中一一读取每个字节(在将其切换到原始模式之后,因此不会发生转换)。 解包获取刚刚读取的字符的字节值,这样“0”读取就会变成 0x30。 选择 latin1 编码,以便此转换保持一致(例如,请参阅 http://www .cs.tut.fi/~jkorpela/latin9.html)。

然后,在命令行上使用 -s 选项指定的值与 512 一起添加到该字节中,以模拟模数运算。 这样,-s 0、-s 256 等是等效的。 我不确定为什么需要这个,因为我认为下面的包会处理这个问题,但我认为他们一定有充分的理由把它放在那里。

然后,将原始字节写入标准输入。

当您在包含字符 012345 的文件(我将数据放在 DATA 部分中)上运行它时,会发生以下情况:

E:\Test> byteshift.pl -s 1 | xxd
0000000: 3132 3334 3536 0b                        123456.

每个字节值都会递增 1。

E:\Test> byteshift.pl -s 257 | xxd
0000000: 3132 3334 3536 0b                        123456.

记住257 % 256 = 1。即:

$byte += $opt_s;
$byte %= 256;

相当于代码中使用的单步。

很久以后:好吧,我不懂 C#,但这是我使用在线文档拼凑出来的内容。 了解 C# 的人应该解决这个问题:

using System;
using System.IO;

class BinaryRW {
    static void Main(string[] args) {
        BinaryWriter binWriter = new BinaryWriter(
                Console.OpenStandardOutput()
                );
        BinaryReader binReader = new BinaryReader(
                Console.OpenStandardInput()
                );

        int delta;

        if ( args.Length < 1 
                || ! int.TryParse( args[0], out delta ) )
        {
            Console.WriteLine(
                    "Provide a non-negative delta on the command line"
                    );
        } 
        else {       
            try  {
                while ( true ) {
                    int bin = binReader.ReadByte();
                    byte bout = (byte) ( ( bin + delta ) % 256 );
                    binWriter.Write( bout );
                }
            }

            catch(EndOfStreamException) { }

            catch(ObjectDisposedException) { }

            catch(IOException e) {
                Console.WriteLine( e );        
            }

            finally {
                binWriter.Close();
                binReader.Close();

            }
        }
    }
}

E:\Test> xxd bin
0000000: 3031 3233 3435 0d0a 0d0a                 012345....

E:\Test> b 0 < bin | xxd
0000000: 3031 3233 3435 0d0a 0d0a                 012345....

E:\Test> b 32 < bin | xxd
0000000: 5051 5253 5455 2d2a 2d2a                 PQRSTU-*-*

E:\Test> b 257 < bin | xxd
0000000: 3132 3334 3536 0e0b 0e0b                 123456....

What the code does is this: Read each byte from standard input one by one (after switching it into raw mode so no translation occurs). The unpack gets the byte value of the character just read so that a '0' read turns into 0x30. The latin1 encoding is selected so that this conversion is consistent (e.g. see http://www.cs.tut.fi/~jkorpela/latin9.html).

Then the value specified on the command line with the -s option is added to this byte along with 512 to simulate a modulus operation. This way, -s 0, -s 256 etc are equivalent. I am not sure why this is needed because I would have assumed the following pack took care of that but I think they must have had good reason to put it in there.

Then, write the raw byte out to standard input.

Here is what happens when you run it on a file containing the characters 012345 (I put the data in the DATA section):

E:\Test> byteshift.pl -s 1 | xxd
0000000: 3132 3334 3536 0b                        123456.

Each byte value is incremented by one.

E:\Test> byteshift.pl -s 257 | xxd
0000000: 3132 3334 3536 0b                        123456.

Remember 257 % 256 = 1. That is:

$byte += $opt_s;
$byte %= 256;

is equivalent to the single step used in the code.

Much later: OK, I do not know C# but here is what I was able to piece together using online documentation. Someone who knows C# should fix this:

using System;
using System.IO;

class BinaryRW {
    static void Main(string[] args) {
        BinaryWriter binWriter = new BinaryWriter(
                Console.OpenStandardOutput()
                );
        BinaryReader binReader = new BinaryReader(
                Console.OpenStandardInput()
                );

        int delta;

        if ( args.Length < 1 
                || ! int.TryParse( args[0], out delta ) )
        {
            Console.WriteLine(
                    "Provide a non-negative delta on the command line"
                    );
        } 
        else {       
            try  {
                while ( true ) {
                    int bin = binReader.ReadByte();
                    byte bout = (byte) ( ( bin + delta ) % 256 );
                    binWriter.Write( bout );
                }
            }

            catch(EndOfStreamException) { }

            catch(ObjectDisposedException) { }

            catch(IOException e) {
                Console.WriteLine( e );        
            }

            finally {
                binWriter.Close();
                binReader.Close();

            }
        }
    }
}

E:\Test> xxd bin
0000000: 3031 3233 3435 0d0a 0d0a                 012345....

E:\Test> b 0 < bin | xxd
0000000: 3031 3233 3435 0d0a 0d0a                 012345....

E:\Test> b 32 < bin | xxd
0000000: 5051 5253 5455 2d2a 2d2a                 PQRSTU-*-*

E:\Test> b 257 < bin | xxd
0000000: 3132 3334 3536 0e0b 0e0b                 123456....
迟月 2024-07-26 05:26:38

从其他答案来看,C# 中的等效内容如下所示:

using(Stream sIn = new FileStream(inPath))
{
  using(Stream sOut = new FileStream(outPath))
  {
    int b = sIn.ReadByte();
    while(b >= 0)
    {
      b = (byte)b+1; // or some other value
      sOut.WriteByte((byte)b);
      b = sIn.ReadByte();
    }
    sOut.Close();
  }
  sIn.Close();
}

Judging by the other answers the equivalent in C# would look something like this:

using(Stream sIn = new FileStream(inPath))
{
  using(Stream sOut = new FileStream(outPath))
  {
    int b = sIn.ReadByte();
    while(b >= 0)
    {
      b = (byte)b+1; // or some other value
      sOut.WriteByte((byte)b);
      b = sIn.ReadByte();
    }
    sOut.Close();
  }
  sIn.Close();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文