使用2个mmaped数组的std :: merge?

时间:2011-01-31 09:46:26

标签: c++ c unix stl mmap

我正在编写两个文本文件,每行写一个整数。 我从驱动器中读取它们,我想对它们进行排序合并。 两个输入文件“1piece0”和“1piece1”具有排序整数列表。 输出文件的大小与两个文件组合在一起,但不是那么多整数。 问题:两个输入文件有25430000行,而输出文件应该有50860000行,但它只有17259463行。 这是我目前的代码。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <algorithm>

#define FILESIZE 25430000 * sizeof(int)
#define FILE0 279288034
#define FILE1 279287226
int main()
{
    int i;
    int fd;
    int fd2;
    int fd3;
    int result;
    int *map;
    int *map2;
    int *map3;

    fd3 = open( "file.out", O_RDWR | O_CREAT | O_TRUNC, (mode_t)0755);
    if ( fd3 == -1 ) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }
    result = lseek(fd3, FILE0 + FILE1 - 1, SEEK_SET );
    if(result == -1) {
        close(fd);
        perror("Error calling lseek\n");
        exit(EXIT_FAILURE);
    }

    result = write(fd3,"",1);
    if( result != 1 ) {
        close(fd3);
        perror("error writing last byte");
        exit(EXIT_FAILURE);
    }
    map3 =(int *) mmap(0, FILE0 + FILE1, PROT_READ | PROT_WRITE, MAP_SHARED, fd3, 0);
    if( map == MAP_FAILED ) {
        close(fd);
        perror("Error mmapinG fd3");
        exit(EXIT_FAILURE);
    }


    fd = open( "1piece0", O_RDONLY );
    if( fd == -1 ) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    map = (int *)mmap(0, FILE0, PROT_READ, MAP_SHARED, fd, 0 );
    if( map == MAP_FAILED ) {
        close(fd);
        perror("error mapping file");
        exit(EXIT_FAILURE);
    }

    fd2 = open( "1piece1", O_RDONLY );
    if( fd2 == -1 ) {
        perror("Error opening file for writing");
        exit(EXIT_FAILURE);
    }

    map2 = (int *)mmap(0, FILE1, PROT_READ, MAP_SHARED, fd2, 0 );
    if( map == MAP_FAILED ) {
        close(fd2);
        perror("error mapping file");
        exit(EXIT_FAILURE);
    }

//  while(1);
    std::merge( map, map + 25430000, map2, map2 + 25430000, map3 );

    if(munmap(map, FILE0 ) == -1 ) {
        perror("error unmapping map");
    }
    close(fd);

    if(munmap(map3, FILE0 + FILE1 ) == -1 ) {
        perror("error unmapping map3");
    }
    close(fd3);

    if(munmap(map2, FILE1 ) == -1 ) {
        perror("error unmapping map2");
    }
    close(fd2);

    return 0;
}

你能告诉我我做错了吗?

更新:按行我的意思是整数,然后是换行符。

2 个答案:

答案 0 :(得分:2)

“line”是什么意思?

当你记忆地图时,它将数据视为内存,在这里你就像一个整数数组一样读它。因此,输入必须是本机二进制格式(即以相同的方式存储字节,相同的大小和相同的字节顺序),25430000是您从每个集合中读取的整数。

你的输入是如何存储的?

这里有很多“神奇数字”。

答案 1 :(得分:2)

您不能将文本行视为二进制blob作为int指针进行操作。

您可以将文本文件视为文本extracted and used

void merge_ints(std::istream &a_in, std::istream &b_in, std::ostream &out) {
  int a, b;
  std::istream *remaining = 0;
  if (!(a_in >> a)) {
    remaining = &b_in;
  }
  else if (!(b_in >> b)) {
    out << a << '\n';
    remaining = &a_in;
  }
  else while (a_in && b_in) {
    if (a < b) {
      out << a << '\n';
      if (!(a_in >> a)) {
        out << b << '\n';
        remaining = &b_in;
      }
    }
    else {
      out << b << '\n';
      if (!(b_in >> b)) {
        out << a << '\n';
        remaining = &a_in;
      }
    }
  }
  for (int x; *remaining >> x;) {
    out << x << '\n';
  }
}

Taking advantage of std::merge

void merge_ints(std::istream &a, std::istream &b, std::ostream &out) {
  typedef std::istream_iterator<int> In;
  std::merge(In(a), In(), In(b), In(), std::ostream_iterator<int>(out, "\n"));
}

int main() {
  stringstream a ("1\n3\n5\n"), b ("2\n4\n6\n7\n"), out;
  merge_ints(a, b, out);
  cout << out.str();
}