سؤال

أحتاج إلى تحويل البايت لملف نصي.لا أعرف شيئًا على الإطلاق عن لغة 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 ملف نصي.

وأما بقية تفاصيل محددة لكيف بيرل تلك الأشياء. getopts () هي وظيفة (من وحدة Getopt :: الأمراض المنقولة جنسيا) الذي يعالج رموز تبديل سطر الأوامر. binmode () يضع filehandles في وضع raw لتجاوز أي من السحر الذي بيرل يفعل عادة خلال I / O. وsysread () وsyswrite () تستخدم وظائف للوصول تيار على مستوى منخفض. حزمة () وفك () تستخدم وظائف القراءة والكتابة البيانات الثنائية. بيرل لا تفعل أنواع الأم.

وهذا من شأنه أن يكون تافها لإعادة تنفيذ في 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();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top