C# 帮助进行字节移位

C# 帮助进行字节移位,c#,perl,byte-shifting,C#,Perl,Byte Shifting,我需要对文本文件进行字节移位。我对perl一无所知,但我在perl中找到了一段完美的代码,名为()。这正是我想做的,但我需要用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 >outfil

我需要对文本文件进行字节移位。我对perl一无所知,但我在perl中找到了一段完美的代码,名为()。这正是我想做的,但我需要用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;
}
#/usr/bin/perl
#要执行7的字节移位
#要解码:moz-byteshift.pl-s-7 outfile
#要编码:moz-byteshift.pl-s 7 outfile
#执行13的字节移位
#要解码:moz-byteshift.pl-s-13 outfile
#要编码:moz-byteshift.pl-s 13 outfile
使用“拉丁1”编码;
严格使用;
使用Getopt::Std;
使用变量qw/$opt_s/;
getopts(“s:”);
如果(!已定义$opt_s){
“缺少班次”\n;
}
我的$buffer;
而(1){
binmode(标准输入,“:原始”);
my$n=sysread STDIN,$buffer,1;
如果($n==0){
最后;
}
my$byte=unpack(“c”,$buffer);
$byte+=512+$opt\s;
$buffer=pack(“c”,$byte);
binmode(标准输出,“:原始”);
syswrite标准输出,$buffer,1;
}
如果有人能至少解释一下perl脚本是如何工作的,那就太好了。C#中的等效示例代码更好。=)


谢谢你的帮助。

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

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


在C中重新实现这一点很简单。我建议这样做(如果需要,从C绑定到它),而不是直接移植到C。

代码的作用是:从标准输入中逐个读取每个字节(在将其切换到原始模式后,这样就不会发生转换)。解包获取刚刚读取的字符的字节值,以便“0”读取变为0x30。选择拉丁1编码,以确保此转换一致(例如,请参阅)

然后,命令行中使用-s选项指定的值与512一起添加到此字节,以模拟模运算。这样,-s0,-s256等是等效的。我不知道为什么需要这样做,因为我会假设下面的包已经处理好了,但我认为他们一定有很好的理由把它放在那里

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

下面是在包含字符012345的文件上运行它时发生的情况(我将数据放在data部分):

每个字节值递增一

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....
使用系统;
使用System.IO;
类BinaryRW{
静态void Main(字符串[]参数){
BinaryWriter=新的BinaryWriter(
Console.OpenStandardOutput()
);
BinaryReader=新的BinaryReader(
Console.OpenStandardInput()
);
内特三角洲;
如果(参数长度<1
||!int.TryParse(args[0],out delta))
{
控制台写入线(
“在命令行上提供非负增量”
);
} 
否则{
试一试{
while(true){
int bin=binReader.ReadByte();
字节bout=(字节)((bin+delta)%256);
写作(布特);
}
}
catch(EndOfStreamException){}
catch(ObjectDisposedException){}
捕获(IOE异常){
控制台写入线(e);
}
最后{
binWriter.Close();
binReader.Close();
}
}
}
}
E:\Test>xxd箱
0000000:3031 3233 3435 0d0a 0d0a 012345。。。。
E:\Test>b0B32B257
根据其他答案判断,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();
}

谢谢这很有帮助。我想我不明白的是它会做什么样的转换。它是否需要这样的字节数组:byte[]{1,2,3,4,5}并(移位1)生成:byte[]{5,1,2,3,4}?还是将每个字节的位移位,将:byte[]{0000000 10000000000011}转换为(移位1):byte[]{1000000000000110000001}?将其称为“移位”有点用词不当。它不移动位或字节。它对每个字节的值应用偏移量。如果原始数据的字节值为1、2、3,并且您指定了“-s 5”,那么结果将是6、7、8。那么它会添加到字节值中吗?所以当位移为10000001时,会变成10000010000011001,依此类推?安德鲁:没错。还请注意,这些值是环绕的。i、 e.0xFE+0x04=0x02。这使得转换是可逆的,我不明白。如果,正如您在一条评论中所说,您实际上不知道perl脚本的作用,那么您如何知道它是您想要做的呢?一位同事正在使用该脚本来执行我现在必须实现的功能。这就是为什么。我认为512应该是一个偏差,以迫使值包装,而不是饱和。不过,我认为这没有必要(至少在Perl中没有)。谢谢!那很好用。我不是
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();
}