XOR von Dateien/Stdstreams erzeugen, wie?



  • Siehe:
    http://www.linuxforen.de/forums/showthread.php?t=230222

    Kann jemand mein python-programm auf ANSI C portieren?

    Mich interessiert vor allem, wie ihr C-Programmierer das effizient macht,
    beziehend auf Buffer usw., weil in meine Version lese ich die Files nur Byte für Byte. Nicht gerade schnell.

    PS: Das ist keine Hausaufgabe von mir - aus dem alter bin ich raus, würde mein Scriptlein nur wirklich gerne in effizienter C Version sehen.

    Danke.

    xor.py:

    #!/usr/bin/env python
    
    import sys
    
    infile1=open(sys.argv[1],'r')
    infile2=open(sys.argv[2],'r')
    
    outfile=[]
    
    size=len(infile1.read())
    infile1.seek(0)
    
    for i in xrange(size):
        outfile.append(chr(ord(infile1.read(1)) ^ ord(infile2.read(1))))
    
    infile1.close()
    infile2.close()
    
    sys.stdout.write("".join(outfile))
    


  • Ich würde das fast 1:1 umsetzen (wobei outfile wegfällt, da ich sofort ausgebe, und ich die Längenberechnung ausfallen lasse (das Dateiende erkenne ich per feof()):

    FILE* infile1,infile2;
    
    //infile1=open(sys.argv[1],'r')
    infile1=fopen(argv[1],"r");//oder "rb"
    //infile2=open(sys.argv[2],'r')
    infile2=fopen(argv[2],"r");
    
    //for i in xrange(size):
    //    outfile.append(chr(ord(infile1.read(1)) ^ ord(infile2.read(1))))
    while(!feof(infile1)&&!feof(infile2)
      putc((char)(fgetc(infile1) ^ fgetc(infile2),stdout);
    
    //infile1.close()
    fclose(infile1);
    //infile2.close()
    fclose(infile2);
    


  • #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
      FILE* infile1,infile2;
    
      if (argc != 3)
      {
        fprintf(stderr, "Aufruf: %s datei1 datei2\n", argv[0]);
        return -1;
      }
    
      //infile1=open(sys.argv[1],'r')
      infile1=fopen(argv[1],"r");//oder "rb"
      //infile2=open(sys.argv[2],'r')
      infile2=fopen(argv[2],"r");
    
      //for i in xrange(size):
      //    outfile.append(chr(ord(infile1.read(1)) ^ ord(infile2.read(1))))
      while(!feof(infile1)&&!feof(infile2)
        putc((char)(fgetc(infile1) ^ fgetc(infile2),stdout);
    
      //infile1.close()
      fclose(infile1);
      //infile2.close()
      fclose(infile2);
    
      return 0;
    }
    

    CStoll: Wenn Du schon mal angefangen hast, dann geben wir ihm doch noch den Programmrahmen, so daß er das nur noch über den Compiler zu jagen braucht.



  • 😕 Ich werd's mir merken für's nächste Mal



  • CStoll schrieb:

    😕 Ich werd's mir merken für's nächste Mal

    Lass gut sein, Mitdenken im Wert von zwei Zeilen muss drinsein.



  • @nman

    Ja gut, so ganz der blutigste C beginner bin ich nun auch wieder nicht, dass ich das blabla drumherum dringend brächte (als linux-user kennt man das übliche #inculde...).
    Ausserdem fand ich es gut, wie er das gemacht hat - immer schön den entsprechenden C code unterm python code angeben.

    Eigentlich bin ich nur darüber enttäuscht, dass es anscheinend nicht schneller geht als byte-für-byte.

    Ich hatte mir von C Cracks etwas mehr erhofft, ihr als typische Daten-analytker und -verarbeiter müsstet doch dazu nen Einfall haben.
    (...Im Gegensatz zu mir Python-"Es funktioniert und ich 10 Zeilen lang, was willst du mehr?"-Anfänger zumindest...)

    🙂

    Trotzdem vielen Dank für die raschen Antworten.



  • lfhelper schrieb:

    Eigentlich bin ich nur darüber enttäuscht, dass es anscheinend nicht schneller geht als byte-für-byte.

    Naja, Du willst Byte für Byte verxorn, das musst Du eben auch Byte für Byte machen.

    Ich hatte mir von C Cracks etwas mehr erhofft, ihr als typische Daten-analytker und -verarbeiter müsstet doch dazu nen Einfall haben.

    Bin zwar kein C-Crack, aber Du kannst ja mal probieren, ob das mit man: mmap(2) oä schneller wird; sehr viel wird vmtl. nicht rauszuholen sein.

    Bei IO-intensiven Sachen wirst Du aber höchstwahrscheinlich keine riesigen Unterschiede zwischen Python und C++ feststellen können, weil Du die meiste Zeit auf die Festplatte warten müssen wirst.



  • Du kannst aber mehrere Bytes gleichzeitig XORen. Stichwort: SIMD



  • Du könntest natürlich auch beide Dateien in größeren Blöcken einlesen, diese Blöcke miteinander verrechnen und das Ergebnis zurückschreiben.



  • Ich wollte es gerade sagen: Das Problem wird aller Wahrscheinlichkeit nach nicht das byteweise XOR sein, sondern das byteweise lesen und schreiben.



  • FILE* ist so etwas wie fstream in C++. Er verwaltet einen Puffer, so daß byteweises lesen mittels fgetc und byteweises schreiben mittels putc nicht bedeutet, daß für jedes Byte ein Systemaufruf erfolgt.

    Ihr könnt ja mal spasseshalber das gleiche mit open(2), read(2), write(2) und close(2). Da werdet ihr warscheinlich einen Unterschied bemerken. Interessant ist auch strace. Das Tool gibt die ausgeführten Systemaufrufe eines Prozesses aus. Da sieht man auch wie das arbeitet.

    Ich gehe davon aus, daß Python automatisch gepuffert liest und schreibt, so daß die Geschwindigkeit ähnlich ist.

    Grundsätzlich überwiegt hier das I/O, so daß die verwendete Programmiersprache kaum ins Gewicht fällt. Es wundert mich nicht, daß Python nicht messbar langsamer ist.

    Mit mmap wird sich das nicht wesentlich ändern, da auch hier die Daten irgendwie von der Platte in den Speicher und zurück transportiert werden muß.

    Tntnet


Anmelden zum Antworten