2016-11-03 7 views
2

우리는 압축 된 데이터를 많이 가지고 있습니다. 압축 된 데이터는 실제로 XML 파일이 들어있는 디렉토리 및 하위 디렉토리의 압축 된 테이프 아카이브입니다. 예 :Perl의 .tar.bz2 아카이브에서 파일 당 파일 줄 수를 스트리밍 할 수 있습니까?

omega/  
- alpha/ 
    - a/ 
    - file1.xml 
    - file2.xml 
    - file3.xml 
    - b/ 
    - file1.xml 
    - file2.xml 
    - file3.xml 
    - c/ 
    - ... 
- beta/ 
    - a/ 
    - file1.xml 
    - file2.xml 
    - file3.xml 
    - b/ 
    - ... 
    - c/ 
    - ... 
- gamma/ 
    - a/ 
    - ... 
    - b/ 
    - ... 
    - c/ 
    - ... 

결과가 될 것 같은 omega.tar.bz2 같은 파일이 파일은 수백 기가 바이트의 크기를 도달 할 수 있습니다.

파일 형식이 인 것으로 알고 있지만 필요한 경우에도 해당 내용을 계속 사용할 수 있으면 좋을 것입니다. 따라서 Perl에서 이러한 파일을 스트리밍 방식으로 읽을 수 있는지, 즉 디스크의 모든 항목을 압축 해제하고 압축을 풀지 않고 전체*.tar.bz2 파일을 메모리에로드하지 않고 궁금해했습니다.

저는 IO::Uncompress으로 Bunzip2를 사용할 수 있습니다. 그러나 내가 볼 수 있고 테스트 한 한대로, 이것은 전체 파일을 우리의 큰 파일로는 메모리로 읽어 들일 것입니다. Bunzipping에 대한 예제 코드 (TAR 제외). 계정에 TAR 촬영

use strict; 
use warnings; 
use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ; 

my $filename = '/path/to/file/file1.xml.bz2'; 
open(my $fh, '<', $filename) 
    or die "Could not open file '$filename' $!"; 

my $buffer ; 
bunzip2 $filename => \$buffer 
    or die "bunzip2 failed: $Bunzip2Error\n"; 

print STDOUT "$buffer\n"; 

, 또한 Extract Object.tar.bz2 파일 (유형 tbz를) 읽을 수있는 Archive::Extract 모듈이있다, 그러나 다시이 불가능 메모리에 전체 파일을 읽을 것입니다 우리의 거대한 파일.

주제에 대한 자체 연구로 인해 BZIP2의 TAR을 스트리밍 방식으로 읽을 수 없다고 생각합니다. 압축에 대한 경험이 없기 때문에 많은 데이터 블록이 주어진다면 파일 라인을 재구성하는 방법이있을 수 있습니다.

Tl : dr : BZIP2 압축 TAR 아카이브에서 파일 내용 (줄당 또는 유사한 내용)을 스트리밍 할 수 있습니까?

답변

2

bzip2 입력 청크를 청크 (즉, 스트림)에서 압축을 풀 수있는 Compress::Raw::Bzip2이 있습니다. 그러나 .tar.bz2는 먼저 bzip2로 압축 된 tar 파일이므로 원하는 데이터에 액세스하기 전에 먼저 tar 파일의 파일 위치까지 모든 데이터의 압축을 풀어야합니다. 즉, 모든 파일을 압축 해제하지 않고이 파일까지 찾으십시오. 괜찮 으면 Archive::Tar::Stream을 사용할 수 있습니다. 즉, bzip2 디코더의 입력을 스트리밍 타르 파서에 공급할 수 있습니다. 필자는 직접 사용한 적이 없지만 이런 종류의 사용 사례를 위해 정확히 개발 된 것처럼 보입니다.

입력 파일의 형식을 변경할 수있는 옵션이있는 경우 전체 압축 파일 (예 : .tar.bz2)을 압축하는 대신 ZIP처럼 압축 파일을 저장하는 형식을 사용하는 것이 좋습니다. . 이렇게하면 특정 압축 파일을 쉽게 찾고이 파일까지 모든 파일 대신 압축을 풀 수 있습니다.

+0

감사합니다. 그러나 ZIP을 사용하는 경우 압축 파일에 액세스하려면 먼저 전체 ZIP을 압축 해제해야합니까? 이것은 모든 파일을 먼저 bzip하고 * tarring하는 것과 비슷합니까? –

+0

@BramVanroy : ZIP을 사용하면 파일이 압축 파일 내에서 압축됩니다. 즉, 특정 파일을 찾아서이 파일까지 아카이브의 모든 내용을 압축 해제하지 않고 압축을 풀 수 있습니다. –

0

IO :: Compress 및 IO :: Uncompress 모듈은 모두 IO :: Uncompress :: Bunzip2를 비롯한 스트리밍을 지원합니다. 보여준 예제 코드 (아래 참조)는 파일에서 모든 압축 된 데이터를 읽고 한 번에 버퍼에 압축을 풀려는 일반적인 사용 사례에 대해 편리한 방법 (bunzip2)을 사용하고 있습니다.여기

my $buffer ; 
bunzip2 $filename => \$buffer 
    or die "bunzip2 failed: $Bunzip2Error\n"; 

는 스트리밍 bunzip2는 유스 케이스

my $bz = IO::Uncompress::Bunzip2->new($filename); 

# $bz is a regular Perl filehandle, so can read it a line at a time 
while (<$bz>) 
{ 
    .... 
} 

# or a bock at a time 
read($bz, $buffer, 1024); 

close $gz; 

당신이 펄 핸들을 받아 자체가 당신이 그것을에게 IO :: 압축 풀기를 줄 수있는 스트리밍하는 타르 모듈을 찾을 수있는 경우의 사용입니다 :: Bubzip2 개체.

또 다른 옵션은 "real"타사 바이너리를 처리하도록하는 것입니다. 더 최근 버전의 gnu tar는 압축을 자동으로 감지하여 tar을 stdout에 쓸 수 있습니다. 그래서 다음과 같이 tar 명령에 파일 핸들을 열면됩니다.

open my $data, "tar -Of $file.tar.bz2 |"; 

while (<$data>) 
{ 
    .... 
}