2개의 바이너리 파일의 비트별 OR

2개의 바이너리 파일의 비트별 OR

얼마 전에는 죽어가는 하드 드라이브에 대해 두 번의 복구 시도를 했습니다. 먼저 해당 드라이브를 실행(GNU) ddrescue한 다음 dd수동으로 직접 검색했습니다. 저는 두 이미지를 최대한 활용하고 싶었습니다. 파일의 빈 부분은 0이므로 비트별 AND는 두 파일을 병합하는 데 충분합니다.

두 입력 파일의 OR인 파일을 생성할 수 있는 유틸리티가 있습니까?

(저는 ArchLinux를 사용하고 있지만 리포지토리에 없으면 소스에서 설치하겠습니다)

답변1

이 작업을 수행할 수 있는 유틸리티는 없지만 이를 수행하는 프로그램을 작성하는 것은 쉬울 것입니다. 다음은 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()

또는 더 빠르게 실행되는 C 프로그램(그러나 눈에 띄지 않는 버그가 있을 가능성이 더 높음):

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

답변2

파이썬

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

한 번에 1024바이트를 읽기 때문에 Chris의 Python 솔루션보다 약 10배 빠릅니다. 또한 이 with open모드를 사용하는 이유는 파일을 닫을 때(예: 오류 발생 시) 더 안정적이기 때문입니다.

이것은 Python 3.6.3(2개의 부분 토렌트 파일을 성공적으로 병합)에서 작동하는 것 같지만 철저하게 테스트되지 않았습니다.

if ...: break패턴을 제거하고 대신 사용할 수도 있습니다.while in1 or in2:

답변3

이는 비트 OR이 아니지만 0(전체 블록)과 함께 작동합니다.

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

sparse소스 파일에 0 쓰기를 건너뛰기 때문입니다 .

따라서 baz는 bar처럼 보일 것입니다. bar에서는 0이지만 foo에서는 0이 아닌 것은 무엇이든 추가됩니다.

즉, foo와 bar에 동일하지 않은 0이 아닌 데이터가 있으면 bar가 승리합니다.

관련 정보