2011-01-31 65 views
2

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

#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; 
} 

你能告诉我我做错了什么吗?

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

+1

告诉我们更多关于什么错误。 – 2011-01-31 09:49:17

+0

@Jens - 这些文件的格式是整数,然后是换行符。 所以我想排序合并它们。我想我不能将他们映射。 确切的问题是输出文件中没有足够的行。 – 2011-01-31 10:15:38

+0

map2和map3旁边的if条件不应该检查map2和map3,而不是map? – yasouser 2011-02-01 14:13:36

回答

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(); 
} 
2

你是什么意思的“线”?

当你处理内存映射时,它会像处理内存一样处理数据,并且在这里你像读取数组一样读取它。因此,输入必须是本地二进制格式(即以相同方式存储的字节,相同的大小和相同的字节序),并且25430000是您从每个集合中读取的整数。

难道你的输入是如何存储的?

这里有很多“幻数”。