我需要对文本文件进行字节移位。我对perl一无所知,但我在perl中发现了一段名为moz-byteshift.pl(documentation)的完美代码。这正是我想要做的,但我需要在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 :(得分:4)
没什么好说的。它一次读取一个字节的文件,通过任意值(通过-s标志指定)调整每个字节的值,并写出调整后的字节。它是文本文件的ROT-13加密的二进制等价物。
其余细节特定于Perl如何做这些事情。 getopts()是一个处理命令行开关的函数(来自Getopt :: Std模块)。 binmode()将文件句柄置于原始模式,以绕过Perl在I / O期间通常所做的任何魔术。 sysread()和syswrite()函数用于低级流访问。 pack()和unpack()函数用于读写二进制数据; Perl不做本机类型。
在C中重新实现这将是微不足道的。我建议这样做(并在需要时从C#绑定它)而不是直接移植到C#。
答案 1 :(得分:1)
代码的作用是:逐个读取标准输入中的每个字节(在将其切换到原始模式后,不进行转换)。 unpack获取刚刚读取的字符的字节值,以便'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....
答案 2 :(得分:1)
根据其他答案判断,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();
}