bit a bit-OR 2 archivos binarios

bit a bit-OR 2 archivos binarios

Hace un tiempo hice 2 intentos de rescate en un disco duro moribundo; Primero ejecuté (GNU) ddrescuey luego directamente ddcon la búsqueda manual. Quiero obtener lo mejor de ambas imágenes. Dado que cualquier tramo vacío en los archivos será solo 0, el AND bit a bit debería ser suficiente para fusionar los dos archivos.

¿Existe alguna utilidad que me permita crear un archivo que sea el OR de dos archivos de entrada?

(Estoy usando ArchLinux, pero estoy feliz de instalarlo desde la fuente si no está en los repositorios)

Respuesta1

No conozco ninguna utilidad que haga esto, pero debería ser bastante fácil escribir un programa para hacerlo. Aquí hay un ejemplo esquelético en 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()

O un programa en C que debería ejecutarse más rápido (pero es mucho más probable que tenga un error desapercibido):

#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;
    }
}

Respuesta2

Pitón

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

Esto es aproximadamente 10 veces más rápido que la solución Python de Chris debido a que lee 1024 bytes a la vez. También utiliza el with openpatrón, ya que es más fiable para cerrar archivos (por ejemplo, en caso de error).

Esto parece funcionar para mí con Python 3.6.3 (fusionando con éxito 2 archivos torrent parciales), pero no se ha probado exhaustivamente.

Quizás el if ...: breakpatrón podría eliminarse y en su lugar utilizarwhile in1 or in2:

Respuesta3

Esto no es bit a bit, pero funciona para (bloques enteros de) ceros:

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

Debido a sparseque omite escribir cualquier cosa que sea cero en el archivo fuente.

Entonces baz se verá como bar, más lo que fuera cero en bar pero no cero en foo.

En otras palabras, si hay datos distintos de cero que no son idénticos en foo y bar, bar gana.

información relacionada