Question

Je dois octet déplacer un fichier texte. Je ne sais absolument rien perl, mais j'ai trouvé un morceau parfaitement travail de code dans perl appelé moz-byteshift.pl ( documentation ). Cela fait exactement ce que je veux faire, mais je dois le faire en C #.

Voici le code source du fichier 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;
}

Si quelqu'un pourrait au moins expliquer comment fonctionne le script perl, ce serait génial. Exemple de code de l'équivalent en C # serait mieux. =)

Merci pour l'aide.

Était-ce utile?

La solution

Ce que le code fait est la suivante: Lire chaque octet d'entrée standard, un par un (après le passage dans le mode brut donc pas de traduction se produit). Le Déballez obtient la valeur d'octet du caractère juste de lire de sorte qu'un « 0 » se transforme en lecture 0x30. Le codage latin1 est choisi pour que cette conversion est cohérente (voir, par exemple http: // www .cs.tut.fi / ~ jkorpela / latin9.html ).

Ensuite, la valeur indiquée sur la ligne de commande avec l'option -s est ajoutée à cet octet en même temps que 512 pour simuler une opération de module. De cette façon, -s 0, -s 256 etc sont équivalents. Je ne sais pas pourquoi cela est nécessaire parce que j'aurais pris le pack suivant a pris soin de cela, mais je pense qu'ils doivent avoir eu de bonnes raisons de le mettre là-dedans.

Ensuite, écrire l'octet brut vers l'entrée standard.

Voici ce qui se passe lorsque vous exécutez sur un fichier contenant les caractères 012345 (je mets les données dans le DATA ):

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

Chaque valeur d'octet est incrémenté d'une unité.

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

Rappelez-vous 257% 256 = 1. C'est:

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

est équivalente à l'étape unique utilisé dans le code.

Beaucoup plus tard: OK, je ne sais pas C #, mais voici ce que j'ai pu rassembler en utilisant la documentation en ligne. Quelqu'un qui sait C # devrait résoudre ce problème:

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

Autres conseils

Il n'y a pas grand-chose à dire. Il lit un fichier d'un octet à la fois, règle la valeur de chaque octet d'une valeur arbitraire (spécifiée par l'indicateur -s), et écrit les octets ajustés. Il est l'équivalent binaire de cryptage ROT-13 d'un fichier texte.

Le reste des détails spécifiques à la façon dont Perl fait ces choses. getopts () est une fonction (à partir du module Getopt :: Std) qui traite les commutateurs de ligne de commande. binmode () met les descripteurs de fichiers en mode brut pour contourner toute la magie que Perl fait normalement au cours d'E / S. Les fonctions sysread () et syswrite () sont utilisées pour l'accès au flux de bas niveau. Le pack () et unpack () fonctions sont utilisées pour lire et écrire des données binaires; Perl ne fait pas les types natifs.

Ce serait trivial de réimplémenter en C. Je vous conseille de faire cela (et se liant à elle à partir de C # le cas échéant) plutôt que le portage vers C # directement.

A en juger par les autres réponses l'équivalent en C # ressemblerait à quelque chose comme ceci:

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top