Помогите со смещением байтов - PullRequest
2 голосов
/ 15 мая 2009

Мне нужно сдвинуть байты текстового файла. Я абсолютно ничего не знаю о 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 # будет лучше. =)

Спасибо за помощь.

Ответы [ 3 ]

4 голосов
/ 15 мая 2009

Сказать особо нечего. Он читает файл по одному байту за раз, корректирует значение каждого байта произвольным значением (указанным через флаг -s) и записывает скорректированные байты. Это двоичный эквивалент шифрования ROT-13 текстового файла.

Остальные детали относятся к тому, как Perl делает эти вещи. getopts () - это функция (из модуля Getopt :: Std), которая обрабатывает ключи командной строки. binmode () переводит файловые дескрипторы в необработанный режим, чтобы обойти любую магию, которую Perl обычно делает во время ввода-вывода. Функции sysread () и syswrite () используются для низкоуровневого доступа к потоку. Функции pack () и unpack () используются для чтения и записи двоичных данных; Perl не поддерживает нативные типы.

Это было бы тривиально для повторной реализации в C. Я бы порекомендовал сделать это (и привязать к нему из C #, если это необходимо), вместо того, чтобы напрямую портировать на C #.

1 голос
/ 15 мая 2009

Судя по другим ответам, эквивалент в 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();
}
1 голос
/ 15 мая 2009

Код выполняет следующие действия: считывает каждый байт со стандартного ввода один за другим (после переключения в необработанный режим, чтобы не происходил перевод). Распаковка получает значение байта только что прочитанного символа, так что чтение «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.

Значение каждого байта увеличивается на единицу.

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....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...