문제
텍스트 파일을 바이트 선택해야합니다. 나는 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;
코드에 사용 된 단일 단계와 동일합니다.
훨씬 나중에 : 좋아, 나는 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 :: std module)입니다. BinMode ()는 파일 핸들을 원시 모드로 넣기 위해 I/O 동안 Perl이 일반적으로하는 마법을 우회합니다. sysread () 및 syswrite () 함수는 저수준 스트림 액세스에 사용됩니다. Pack () 및 Unpack () 함수는 이진 데이터를 읽고 쓰는 데 사용됩니다. 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();
}