2011-01-31 79 views
3

我有一个包含故事数量的大文本文件(大约10 GB)。每个故事从标记$$开始。以下是该文件的示例:如何在不截断记录的情况下将大文本文件分割成大小均匀的块?

$$ 
AA This is story 1 
BB 345 

$$ 

AA This is story 2 
BB 456 

我想将此文件拆分为大小约为250 MB的碎片。但是没有一个故事应该被分成两个不同的文件。

任何人都可以帮我用这个Unix或Perl代码吗?

回答

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 2011-01-31 16:52:44

+0

当然可以。你可以提供一个正则表达式作为你的分裂标准。如果提问者将其设置为/ \ $ \ $ /,那么`csplit`应该做他们想要的。 – CanSpice 2011-01-31 18:02:26

+0

@CanSplice:但是我们的目标不是在正则表达式上分割,而是分割大约每个250Mb,而不会破坏\ $ \ $ \ n分离的块。 csplit不会那样做。 – ysth 2011-01-31 18:52:55

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; 
} 
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"; 
} 
相关问题