2011-01-31 43 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是您從每個集合中讀取的整數。

難道你的輸入是如何存儲的?

這裏有很多「幻數」。