Bitweises ODER 2 Binärdateien

Bitweises ODER 2 Binärdateien

Ich habe vor einiger Zeit zwei Rettungsversuche auf einer sterbenden Festplatte unternommen. ddrescueZuerst habe ich (GNU) ausgeführt und dann direkt ddmit manueller Suche. Ich möchte das Beste aus beiden Bildern herausholen. Da alle leeren Abschnitte in den Dateien nur Nullen sind, sollte ein bitweises UND ausreichen, um die beiden Dateien zusammenzuführen.

Gibt es ein Dienstprogramm, mit dem ich eine Datei erstellen kann, die das ODER zweier Eingabedateien ist?

(Ich verwende ArchLinux, aber ich installiere gerne aus dem Quellcode, wenn dieser nicht in den Repos enthalten ist.)

Antwort1

Ich kenne kein Dienstprogramm, das dies kann, aber es sollte ziemlich einfach sein, ein Programm dafür zu schreiben. Hier ist ein grobes Beispiel in Python:

#!/usr/bin/env python
f=open("/path/to/image1","rb")
g=open("/path/to/image2","rb")
h=open("/path/to/imageMerge","wb") #Output file
while True:
     data1=f.read(1) #Read a byte
     data2=g.read(1) #Read a byte
     if (data1 and data2): #Check that neither file has ended
          h.write(chr(ord(data1) | ord(data2))) #Or the bytes
     elif (data1): #If image1 is longer, clean up
          h.write(data1) 
          data1=f.read()
          h.write(data1)
          break
     elif (data2): #If image2 is longer, clean up
          h.write(data2)
          data2=g.read()
          h.write(data2)
          break
     else: #No cleanup needed if images are same length
          break
f.close()
g.close() 
h.close()

Oder ein C-Programm, das schneller laufen sollte (bei dem aber die Wahrscheinlichkeit eines unbemerkten Fehlers deutlich höher ist):

#include <stdio.h>
#include <string.h>

#define BS 1024

int main() {
    FILE *f1,*f2,*fout;
    size_t bs1,bs2;
    f1=fopen("image1","r");
    f2=fopen("image2","r");
    fout=fopen("imageMerge","w");
    if(!(f1 && f2 && fout))
        return 1;
    char buffer1[BS];
    char buffer2[BS];
    char bufferout[BS];
    while(1) {
        bs1=fread(buffer1,1,BS,f1); //Read files to buffers, BS bytes at a time
        bs2=fread(buffer2,1,BS,f2);
        size_t x;
        for(x=0;bs1 && bs2;--bs1,--bs2,++x) //If we have data in both, 
            bufferout[x]=buffer1[x] | buffer2[x]; //write OR of the two to output buffer
        memcpy(bufferout+x,buffer1+x,bs1); //If bs1 is longer, copy the rest to the output buffer
        memcpy(bufferout+x,buffer2+x,bs2); //If bs2 is longer, copy the rest to the output buffer
        x+=bs1+bs2;
        fwrite(bufferout,1,x,fout);
        if(x!=BS)
            break;
    }
}

Antwort2

Python

with open('file1', 'rb') as in1, open('file2', 'rb') as in2, open('outfile', 'wb') as out:
    while True:
        bytes1 = in1.read(1024)
        bytes2 = in2.read(1024)
        if not bytes1 or not bytes2:
            break
        out.write(bytes(b1 | b2 for (b1, b2) in zip(bytes1, bytes2)))

Dies ist etwa 10-mal schneller als Chris' Python-Lösung, da 1024 Bytes auf einmal gelesen werden. Außerdem wird das with openMuster verwendet, da dies beim Schließen von Dateien (z. B. im Fehlerfall) zuverlässiger ist.

Dies scheint bei mir mit Python 3.6.3 zu funktionieren (erfolgreiches Zusammenführen von 2 partiellen Torrent-Dateien), wurde aber nicht gründlich getestet.

Vielleicht if ...: breakkönnte man das Muster entfernen und stattdessen verwendenwhile in1 or in2:

Antwort3

Dies ist kein bitweises Oder, funktioniert aber für (ganze Blöcke von) Nullen:

dd conv=sparse,notrunc if=foo of=baz
dd conv=sparse,notrunc if=bar of=baz

Dadurch sparsewird das Schreiben von allem, was in der Quelldatei Null ist, übersprungen.

Daher sieht baz wie bar plus alles aus, was in bar Null war, aber nicht Null in foo.

Mit anderen Worten: Wenn es Daten ungleich Null gibt, die in foo und bar nicht identisch sind, gewinnt bar.

verwandte Informationen