2011-01-31 3 views
3

이야기의 수를 포함하는 큰 텍스트 파일 (약 10GB)이 있습니다. 각 이야기는 마커 $$으로 시작됩니다. 다음은 파일의 샘플입니다.큰 텍스트 파일을 레코드를 자르지 않고 짝수 크기의 파일로 분할하는 방법은 무엇입니까?

$$ 
AA This is story 1 
BB 345 

$$ 

AA This is story 2 
BB 456 

이 파일을 약 250MB 크기로 분할하고 싶습니다. 그러나 이야기의 어느 것도 두 개의 다른 파일로 나누어 져야합니다.

누구든지이 문제에 대해 유닉스 나 펄 코드를 도울 수 있습니까?

답변

1

csplit은 원하는 것입니다. split과 동일하지만 패턴을 기반으로합니다. C에서

대체 ++ (안 테스트) :

#include <boost/shared_ptr.hpp> 
#include <sstream> 
#include <iostream> 
#include <fstream> 
#include <string> 

void new_output_file(boost::shared_ptr<std::ofstream> &out, const char *prefix) 
{ 
    static int i = 0; 
    std::ostringstream filename; 
    filename << prefix << "_" << i++; 
    out.reset(new std::ofstream(filename)); 
} 

int main(int argc, char **argv) 
{ 
    std::ifstream in(argv[1]); 
    int i = 0; 
    long size = 0; 
    const long max_size = 200 * 1024 * 1024; 
    std::string line; 
    boost::shared_ptr<std::ofstream> out(NULL); 
    new_output_file(out, argv[2]); 
    while(in.good()) 
    { 
     std::getline(in,line); 
     size += line.length() + 1 /* line termination char */; 
     if(size >= max_size && line.length() && line[0] == '$' && line[1] == '$') 
     { 
      new_output_file(out, argv[2]); 
      size = line.length() + 1; 
     } 
     out << line << std::endl; 
    } 
    return 0; 
} 
+1

전혀 질문에 맞지 않는 것 같습니다. – ysth

+0

물론 있습니다. 분할 기준으로 정규식을 제공 할 수 있습니다. 질문자가/\ $ \ $ /에 그것을 설정하면'csplit'은 그들이 원하는 것을해야합니다. – CanSpice

+0

@CanSplice :하지만 목표는 정규 표현식에서 분리하지 않는 것이고, \ $ \ $ \ n 분리 된 청크를 깨지 않고 약 250Mb를 분할하는 것입니다. csplit은 그렇게하지 않습니다. – ysth

5
use strict; 
use warnings; 
use autodie; 

$/ = "\$\$\n"; 
my $targetsize = 250*1024*1024; 
my $fileprefix = 'chunk'; 
my $outfile = 0; 
my $outfh; 
my $outsize = 0; 
while (my $story = <>) { 
    chomp($story); 
    next unless $story; # disregard initial empty chunk 
    $story = "$/$story"; 

    # no file open yet, or this story takes us farther from the target size 
    if (! $outfile || abs($outsize - $targetsize) < abs($outsize + length($story) - $targetsize)) { 
     ++$outfile; 
     open $outfh, '>', "$fileprefix$outfile"; 
     $outsize = 0; 
    } 

    $outsize += length($story); 
    print $outfh $story; 
} 
+0

아직이 코드를 테스트하지는 않았지만 크기가 10GB 인 대용량 파일을 읽을 수 있다고 생각하십니까? wouldnt 프로그램은 '메모리 부족 시스템'이라는 오류를 던집니까? – Man

+0

@Man : 아니요.이 코드는 한 번에 하나의 스토리 만 메모리에 저장합니다. – ysth

+0

감사합니다. 여기 autodie를 사용하는 것이 무엇인지 궁금 해서요? 필자는 시스템에 설치되지 않았으므로 줄을 주석 처리했지만 이제는 프로그램이 전체 입력 파일을 chunk1에 쓰고 있습니다. – Man

1

내가 ysth의 코드를 수정하고 작업을 발견했다. 생각하시는 분을 제안 해 주시고,이를 개선하기 위해 수정할 수 있습니다.

use strict; 
use warnings; 

my $targetsize = 50*1024*1024; 
my $fileprefix = 'chunk'; 
my $outfile = 0; 
my $outsize = 0; 
my $outfh; 
my $temp=''; 
while (my $line = <>) { 
    chomp($line); 
    next unless $line; 
    # discard initial empty chunk 
    if($line =~ /^\$\$$/ || $outfile == 0){ 
     $outsize += length($temp); 
     if ($outfile == 0 || ($outsize - $targetsize) > 0) { 
       ++$outfile; 
       if($outfh) {close($outfh);} 
       open $outfh, '>', "$fileprefix$outfile"; 
       $outsize = 0; 
     } 
     $temp=''; 
    } 
    $temp = $temp.$line; 
    print $outfh "$line\n"; 
} 
+0

과 같은 것을 얻는다. 파일 핸들이 열려 있으면 close가 먼저 자동으로 닫히지 만 명시 적 close는 아프지 않는다. 너는 그것의 길이를 위해서만 $ temp를 사용하고있다; 대신 각 줄에 $ outsize를 추가 할 수 있습니다. 당신은 이야기 속의 빈 줄을 제거하고 있습니다 - 의도적입니까? 추가하는 길이는 개행을 포함하지 않으므로 약간 꺼집니다. 당신은 chomp와 인쇄물의 \ n을 제거 할 수 있고 $ line eq가 "\ n"이라면 다음에 말할 수 있습니다. – ysth

관련 문제