题
我需要字节移位的文本文件。我知道绝对没有关于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#中相当于示例代码会更好。 =)
感谢您的帮助。
解决方案
什么代码的作用是这样的:由一个阅读来自标准输入的一个的每个字节(将其切换到原始模式后所以没有翻译发生时)。解包得到刚才读的字符的字节值,使得“0”读转化成了的0x30。 LATIN1编码被选择为使得该转换是一致的(例如,参见的http:// WWW .cs.tut.fi /〜jkorpela / latin9.html )。
然后使用-s选项的命令行上指定的值被添加到该字节与512沿以模拟模数操作。通过这种方式,-s 0,-s 256等是等价的。我不知道为什么需要这个,因为我本来认为以下背包中拿出的是护理,但我认为他们必须有充分的理由把它放在那里。
然后,写出来的原始字节到标准输入。
下面是当你在一个包含字符012345文件运行它会发生什么(我把数据在数据部分):
E:\Test> byteshift.pl -s 1 | xxd
0000000: 3132 3334 3536 0b 123456.
每个字节的值被加一。
E:\Test> byteshift.pl -s 257 | xxd
0000000: 3132 3334 3536 0b 123456.
记住257%256 = 1。也就是说:
$byte += $opt_s;
$byte %= 256;
是等效于在代码中使用的单个步骤。
很久以后:OK,我不知道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....
其他提示
有没有太多可讲。它在每次读取一个文件的一个字节,通过任意的值(通过-s标志指定)调整每个字节的值,并写入了调整字节。这是一个文本文件的ROT-13加密二进制等效值。
的其余的细节是特定于Perl的如何做这些事情。 getopts的()是一个函数(来自的Getopt ::标准模块),其处理命令行开关。 binmode()放文件句柄在原始模式绕过任何的是Perl中I / O照常魔法。所述sysread执行()和SYSWRITE()函数用于低级别的流的访问。的pack()的和解压()函数是用来读取和写入的二进制数据; Perl并不做本地类型。
这将是微不足道中C.重新实现我建议这样做,(和从C#结合它如果需要的话),而不是移植到C#直接
通过其他的答案来看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();
}