Pergunta

Eu preciso byte-shift um arquivo de texto. Eu sei absolutamente nada sobre perl, mas eu achei um pedaço perfeitamente de trabalho de código em perl chamado moz-byteshift.pl ( documentação ). Isto faz exatamente o que eu quero fazer, mas eu preciso fazê-lo em C #.

Aqui está o código-fonte do arquivo 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;
}

Se alguém pudesse, pelo menos, explicar como funciona o script de perl, isso seria ótimo. Exemplo de código do equivalente em C # seria melhor. =)

Obrigado pela ajuda.

Foi útil?

Solução

O que o código faz é esta: Leia cada byte de uma entrada padrão por um (após mudar-lo em modo RAW assim nenhuma tradução ocorre). A descompactar obtém o valor byte do personagem acabou de ler para que um '0' ler voltas em 0x30. A codificação latin1 é seleccionada de modo que esta conversão é consistente (ver por exemplo http: // www .cs.tut.fi / ~ jkorpela / latin9.html ).

Em seguida, o valor especificado na linha de comando com a opção -s é adicionado a este byte, juntamente com 512 para simular uma operação de módulo. Desta forma,-s 0, -s 256 etc, são equivalentes. Não estou certo por que isso é necessário, porque eu teria assumido o seguinte pacote cuidou disso, mas eu acho que eles devem ter tido uma boa razão para colocá-lo lá.

Em seguida, escreva o byte-prima para a entrada padrão.

Aqui está o que acontece quando você executá-lo em um arquivo contendo os caracteres 012345 (I colocar os dados no DADOS ):

E:\Test> byteshift.pl -s 1 | xxd
0000000: 3132 3334 3536 0b                        123456.

Cada valor byte é incrementado por um.

E:\Test> byteshift.pl -s 257 | xxd
0000000: 3132 3334 3536 0b                        123456.

Lembre-se de 257% 256 = 1. Ou seja:

$byte += $opt_s;
$byte %= 256;

é equivalente a um único passo usadas no código.

Muito mais tarde: OK, eu não sei C #, mas aqui é o que eu era capaz de juntar usando a documentação online. Alguém que sabe C # deve corrigir isso:

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....

Outras dicas

Não há muito para contar. Ele lê um byte arquivo de cada vez, ajusta o valor de cada byte por um valor arbitrário (especificado via o sinalizador -s), e grava os bytes ajustados. É o equivalente binário do Rot-13 criptografia de um arquivo de texto.

O resto dos detalhes são específicos como Perl faz essas coisas. getopts () é uma função de (a partir do módulo Getopt :: Std) que os processos de linha de comando. binmode () coloca os filehandles em modo RAW para ignorar qualquer da magia que Perl faz normalmente durante a I / O. O sysread () e syswrite () são usadas para o acesso de fluxo de baixo nível. O pack () e descompactar () funções são usadas para ler e gravar dados binários; Perl não fazer tipos nativos.

Este seria trivial para voltar a implementar em C. Eu recomendo fazer isso (e vinculativo a ele de C # se necessário) ao invés de portar diretamente para C #.

A julgar pelas outras respostas o equivalente em C # seria algo parecido com isto:

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();
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top