读书人

多路归并| 代码已有|大量文件读入时报

发布时间: 2012-09-05 15:19:34 作者: rapoo

多路归并| 代码已有|大量文件读入时报fscanf错误
多路归并| 代码已有|大量文件读入时失误

更新:下午在坛子里问了下 fopen支持的最大文件数。
验证了正好是这个问题,fopen换成creatfile
不过下一个问题是:fscanf 换成 逐行读取的readfile
这个细节没有想清楚。
代码对应:
if(fscanf(farray[j], "%d", &data[j]) == EOF)


-------------

昨天看了多路归并,
数据是:1000w个整数,分装到10个子文件。
思路是:排好序好,写到每个子文件,每个文件从头取出一个数,放到数组A,将最小的放进输出文件,
找到最小的那个文件,读入下一个放到数组A;
如此直到所有的数据写到输出文件为止。

调试情况:
先简单:
(总数据,每个文件数据)=(6,2 ), 轻松看到输出。
再回归正题
(总数据,每个文件数据)=(1000w ,100w ),用时40s,复杂度分析:n*logn用时2s,大部分时间用到磁盘io
扩展一下:
看看最多可以分成多少个文件,//背景:经常看到海量数据处理时,分而治之,hash到一千个文件
下面数据量从小到大
(总数据,每个文件数据)=(500,1),可以通过。
(总数据,每个文件数据)=(1000,1),报fscanf错误,错误内容stream==null
二分法找找边界:
(总数据,每个文件数据)=(508,1),可以通过。//0x1fc 对应508
(总数据,每个文件数据)=(509,1),不可以通过。报fscanf错误,错误内容stream==null////0x1fd 对应508

找问题的过程:
1)可能是vs给程序分配内存初始太小吗?
修改了reseverd memory为 10m,不然。
想一想,每个文件都只有1个整数啊,不可能内存问题。
任务管理器也检查了下。
ps:所有内存分配都通过new实现,

2)我怀疑是 文件最多打开数目 (windows文件打开描述符)的问题,
但现在不能确定,也没有查到。

3)文件buffer用完?

尝试setbuffer(stdin,null)
fflush(),依然。

3)问题机器相关吗?
//你运行了就知道了

附问题调试方法:
//修改这2个参数就是
const unsigned int count =500;
const unsigned int number_to_sort =1;






















[解决办法]
兄弟:为什么要用fopen,用fstream
在博客:
这里有详细:
http://www.cnblogs.com/daoluanxiaozi/archive/2012/03/29/2423087.html
具体相关代码这里:

C/C++ code
void merge_sort(int filecnt){    fstream * fs = new fstream[filecnt],ret("ret.txt",ios::out);    int index = 1,temp[MAX_ONCE],eofcnt = 0;    bool * eof_flag = new bool[filecnt];    ::memset(eof_flag,false,filecnt*sizeof(bool));    for(int i=0; i<filecnt; i++)        fs[i].open(create_filename(index++),ios::in);    for(int i=0; i<filecnt; i++)        fs[i] >> temp[i];    while(eofcnt<filecnt)    {            int j = 0;        //    找到第一个未结束处理的文件        while(eof_flag[j])            j++;        int min = temp[j],fileindex = 0;        for(int i=j+1; i<filecnt; i++)        {            if(temp[i]<min && !eof_flag[i])                min = temp[i],fileindex = i;        }// for        ret << min << " ";        fs[fileindex] >> temp[fileindex];        //    末尾判断        if(fs[fileindex].peek()==EOF)            eof_flag[fileindex] = true,            eofcnt++;    }// while    delete [] fs;    delete [] eof_flag;    ret.close();} 

读书人网 >C++

热点推荐