免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 3609 | 回复: 20
打印 上一主题 下一主题

6G文件的排序处理 [复制链接]

论坛徽章:
8
技术图书徽章
日期:2013-08-22 11:21:28未羊
日期:2015-01-19 22:22:25巳蛇
日期:2014-08-11 16:53:08子鼠
日期:2014-05-29 09:04:44摩羯座
日期:2014-04-11 14:15:07丑牛
日期:2014-01-24 12:41:28金牛座
日期:2013-11-21 17:38:28射手座
日期:2015-01-21 08:50:32
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-10-13 15:58 |只看该作者 |正序浏览
论坛中toniz 大大的关于perl大文件排序处理测试(与oracle外部表比较)
http://bbs.chinaunix.net/forum.p ... mp;fromuid=29097174
这个帖子提到对大文件分块后排序合并,如果我想处理两个大文件,这两个文件每四行为一部分的,然后按照每部分的第二行进行排序,并且合并,什么样的程序才能避免大文件导致的时间占用和内存问题呢?(数据库就不考虑了,要存那么多东西需要太大空间了)
——————————————
排序文件:
1.txt:
@12@vip.com#20120307/1
BCDBCDBD
+
AAAAAAAA
@18@vip.com#20120307/1
BBDACCDA
+
AAAAAAAA
...
2.txt
@14@vip.com#20120307/1
AABCCCCD
+
AAAAAAAA
@12@vip.com#20120307/1
BCACACAD
+
AAAAAAAA
...
————————————————
结果:
@14@vip.com#20120307/1
AABCCCCD
+
AAAAAAAA
@18@vip.com#20120307/1
BBDACCDA
+
AAAAAAAA
@12@vip.com#20120307/1
BCACACAD
+
AAAAAAAA
@18@vip.com#20120307/1
BBDACCDA
+
AAAAAAAA
。。。。。
----------------------------------
求个程序学习,谢谢!

论坛徽章:
8
技术图书徽章
日期:2013-08-22 11:21:28未羊
日期:2015-01-19 22:22:25巳蛇
日期:2014-08-11 16:53:08子鼠
日期:2014-05-29 09:04:44摩羯座
日期:2014-04-11 14:15:07丑牛
日期:2014-01-24 12:41:28金牛座
日期:2013-11-21 17:38:28射手座
日期:2015-01-21 08:50:32
21 [报告]
发表于 2013-10-15 09:09 |只看该作者
回复 18# rubyish


    我喜欢这个写法。。。。这里高手太多了

论坛徽章:
8
技术图书徽章
日期:2013-08-22 11:21:28未羊
日期:2015-01-19 22:22:25巳蛇
日期:2014-08-11 16:53:08子鼠
日期:2014-05-29 09:04:44摩羯座
日期:2014-04-11 14:15:07丑牛
日期:2014-01-24 12:41:28金牛座
日期:2013-11-21 17:38:28射手座
日期:2015-01-21 08:50:32
20 [报告]
发表于 2013-10-15 09:08 |只看该作者
回复 17# 104359176


    太感谢了。。。。

论坛徽章:
8
技术图书徽章
日期:2013-08-22 11:21:28未羊
日期:2015-01-19 22:22:25巳蛇
日期:2014-08-11 16:53:08子鼠
日期:2014-05-29 09:04:44摩羯座
日期:2014-04-11 14:15:07丑牛
日期:2014-01-24 12:41:28金牛座
日期:2013-11-21 17:38:28射手座
日期:2015-01-21 08:50:32
19
发表于 2013-10-15 09:07
回复 16# stanley_tam


    对不起,对不起。。。伸手党可耻了~谢谢大大

论坛徽章:
7
戌狗
日期:2013-12-15 20:43:38技术图书徽章
日期:2014-03-05 01:33:12技术图书徽章
日期:2014-03-15 20:31:17未羊
日期:2014-03-25 23:48:20丑牛
日期:2014-04-07 22:37:44巳蛇
日期:2014-04-11 21:58:0915-16赛季CBA联赛之青岛
日期:2016-03-17 20:36:13
18 [报告]
发表于 2013-10-15 00:15 |只看该作者
本帖最后由 rubyish 于 2013-10-14 20:18 编辑

大牛,试试一下:
  1. #!/usr/bin/perl
  2. my $head = 5;  # 或多或少
  3. my %file;
  4. @ARGV = qw/test.txt/;

  5. while (<>) {
  6.     my $line2 = <>;
  7.     my $key = substr $line2, 0, $head;
  8.     unless ( $file{$key} ) {
  9.         open my $f, '>', "/tmp/$key";
  10.         $file{$key} = $f;
  11.     }
  12.     print { $file{$key} } $_, $line2, <>.<>;
  13. }

  14. close $file{$_} for keys %file;
  15. open my $result, '>', 'result';

  16. for my $file ( sort keys %file ) {
  17.     @ARGV = "/tmp/$file";
  18.     my @group;
  19.     push @group, [ $_, ~~<>, <>.<> ] while <>;
  20.     print $result @$_ for sort { $a->[1] cmp $b->[1] } @group;
  21.     unlink "/tmp/$file";
  22. }

  23. print scalar keys %file, ' files: BYE!';
复制代码

求职 : 软件工程师
论坛徽章:
3
程序设计版块每日发帖之星
日期:2015-10-07 06:20:00程序设计版块每日发帖之星
日期:2015-12-13 06:20:00程序设计版块每日发帖之星
日期:2016-05-05 06:20:00
17 [报告]
发表于 2013-10-14 22:53 |只看该作者
本帖最后由 104359176 于 2013-10-14 23:01 编辑

我做了一个函数,先将需要排序的内容提取出来,放在一行上,这样就可以用 sort 工具来排序了。
然后用另外一个函数,将这个排序后的索引文件,重新生成你要的文件。
  1. #!perl

  2. use 5.010;

  3. # 根据索引文件生成结果
  4. sub create_file {
  5.     my ($input_file, $output_file) = @_;
  6.     open(my $input_fh, '<', $input_file)  or die $!;
  7.     open(my $output_fh, '>', $output_file) or die $!;
  8.     while (my $line = <$input_fh>) {
  9.         chomp $line;
  10.         my ($index, $first_line) = split /\s+/, $line;
  11.         my $string = create_string($first_line, $index);
  12.         say {$output_fh} $string;
  13.     }
  14. }

  15. # 根据模板创建记录
  16. sub create_string {
  17.     my ($first_line, $index_line) = @_;
  18.     return "$first_line\n$index_line\n+\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
  19. }   

  20. # 将不同的部分按照索引行提取出来,生成新的文件,一行一条记录
  21. sub filter_index_file {
  22.     my ($input_file, $output_file) = @_;
  23.     open(my $input_fh, '<', $input_file)  or die $!;
  24.     open(my $output_fh, '>', $output_file) or die $!;
  25.     my $line_number = 0;
  26.     my $first_line = '';
  27.     while (my $line = <$input_fh>) {
  28.         chomp $line;
  29.         $line_number++;
  30.         $first_line = $line if ($line_number % 4 == 1);
  31.         if ($line_number % 4 == 2) {
  32.             say {$output_fh} $line . chr(32) . $first_line;
  33.         }
  34.     }
  35.     close $input_fh;
  36.     close $output_fh;
  37. }

  38. filter_index_file('test.txt', 'filter.txt');
  39. system("sort filter.txt > index_sort.txt");
  40. create_file('index_sort.txt', 'sort.txt');   
复制代码
要用的工具 sort 你应该有吧。

论坛徽章:
6
丑牛
日期:2014-03-21 15:42:04子鼠
日期:2014-04-12 11:50:17处女座
日期:2014-09-01 09:25:1115-16赛季CBA联赛之吉林
日期:2015-12-22 14:01:5215-16赛季CBA联赛之广东
日期:2016-03-08 18:49:422016科比退役纪念章
日期:2016-07-06 12:19:55
16 [报告]
发表于 2013-10-14 20:13 |只看该作者
本帖最后由 stanley_tam 于 2013-10-14 21:34 编辑

果然是伸手党。假设文件名为test.txt,一次读取一百万行(看自己需求了,自己改)。。。看你上面的行长度,一百万估计就30M。
不过你要的是第二行排序。。。自己想办法咯{:3_195:}
  1. #!perl
  2. use strict;
  3. use autodie qw{open close};
  4. use v5.10;

  5. our %tmp_files = ();

  6. sub main;
  7. sub split_file_by_line;
  8. sub get_fh;
  9. sub merge_sorted_file;

  10. main();

  11. sub main {
  12.     my $line_number    = 1000000;
  13.     my $big_file       = 'test.txt';
  14.     my $sorted_file    = q{};
  15.     split_file_by_line($big_file, $line_number);

  16.     my $tag = 1;
  17.     while (keys %tmp_files > 1) {
  18.         my ($file1, $file2) = (keys %tmp_files)[0,1];
  19.         my $merged_file = "merge_$tag.txt";
  20.         merge_sorted_file($file1, $file2, $merged_file);
  21.         unlink $file1;
  22.         unlink $file2;

  23.         delete $tmp_files{$file1};
  24.         delete $tmp_files{$file2};

  25.         $tmp_files{$merged_file}++;
  26.         $tag++;
  27.     }
  28.     $sorted_file = (keys %tmp_files)[0];
  29.     print "\$sorted_file => [$sorted_file]\n";
  30.     <STDIN>;
  31. }

  32. sub merge_sorted_file {
  33.     my ($file1, $file2, $output_file) = @_;
  34.     my $fh1 = get_fh('<', $file1);
  35.     my $fh2 = get_fh('<', $file2);
  36.     my $output_fh   = get_fh('>', $output_file);
  37.     my $smaller_one = q{};
  38.     my $larger_one  = q{};

  39.     my $line_f1 = <$fh1>;
  40.     my $line_f2 = <$fh2>;

  41.     chomp $line_f1;
  42.     chomp $line_f2;

  43.     while (1) {
  44.         if ($line_f1 le $line_f2) {
  45.             $smaller_one = $line_f1;
  46.             $larger_one  = $line_f2;

  47.             if (eof $fh1) {
  48.                 say {$output_fh} $smaller_one;
  49.                 say {$output_fh} $larger_one;

  50.                 while (my $line = <$fh2>) {
  51.                     chomp $line;
  52.                     say {$output_fh} $line;
  53.                 }

  54.                 last;
  55.             }
  56.             else {
  57.                 chomp($line_f1 = <$fh1>);
  58.             }
  59.         }
  60.         else {
  61.             $smaller_one = $line_f2;
  62.             $larger_one  = $line_f1;

  63.             if (eof $fh2) {
  64.                 say {$output_fh} $smaller_one;
  65.                 say {$output_fh} $larger_one;

  66.                 while (my $line = <$fh1>) {
  67.                     chomp $line;
  68.                     say {$output_fh} $line;
  69.                 }
  70.                 last;
  71.             }
  72.             else {
  73.                 chomp($line_f2 = <$fh2>);
  74.             }
  75.         }
  76.         say {$output_fh} $smaller_one;
  77.     }

  78.     close $fh1;
  79.     close $fh2;
  80.     close $output_fh;
  81. }

  82. sub split_file_by_line {
  83.     my ($file, $line_number) = @_;
  84.     my $tag = 1;

  85.     my $fh = get_fh('<', $file);

  86.     OUTER:
  87.     while (1) {
  88.         my @lines = ();
  89.         INNER:
  90.         for my $lno (1 .. $line_number){
  91.             last INNER if eof $fh;
  92.             my $line = <$fh>;
  93.             chomp $line;
  94.             push @lines, $line;
  95.         }

  96.         if (scalar @lines) {
  97.             @lines = sort {$a cmp $b} @lines;

  98.             my $tmp_file_name = "tmp_$tag.txt";
  99.             my $tmp_fh = get_fh('>', $tmp_file_name);
  100.             say {$tmp_fh} $_ for @lines;
  101.             close $tmp_fh;

  102.             $tmp_files{$tmp_file_name}++;
  103.             $tag++;
  104.         }
  105.         else {
  106.             last OUTER;
  107.         }
  108.     }
  109. }

  110. sub get_fh {
  111.     my ($mode, $file) = @_;
  112.     my $fh;
  113.     open $fh, $mode, $file;
  114.     return $fh;
  115. }
  116. __END__
复制代码
回复 8# huang6894


   

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
15 [报告]
发表于 2013-10-14 18:35 |只看该作者
当然內存占用越小越慢

论坛徽章:
8
技术图书徽章
日期:2013-08-22 11:21:28未羊
日期:2015-01-19 22:22:25巳蛇
日期:2014-08-11 16:53:08子鼠
日期:2014-05-29 09:04:44摩羯座
日期:2014-04-11 14:15:07丑牛
日期:2014-01-24 12:41:28金牛座
日期:2013-11-21 17:38:28射手座
日期:2015-01-21 08:50:32
14 [报告]
发表于 2013-10-14 18:29 |只看该作者
回复 13# pitonas


    其实就是想测试如何在低cpu的条件下实现排序。。。cpu是个模拟的条件,当然占用越小越好

论坛徽章:
5
丑牛
日期:2014-01-21 08:26:26卯兔
日期:2014-03-11 06:37:43天秤座
日期:2014-03-25 08:52:52寅虎
日期:2014-04-19 11:39:48午马
日期:2014-08-06 03:56:58
13 [报告]
发表于 2013-10-14 18:02 |只看该作者
多少內存?
  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP