读取多个文件并行缓冲区

时间:2014-02-14 05:44:36

标签: c++ multithreading winapi filesystems buffer

我正在一个项目中工作,我必须读取一组文件并将其放入缓冲区。该列表包含小文件和大文件。我必须阅读这些文件,为了提高效率,我尝试在多个线程。每个线程将从文件名向量中取出一个文件并开始读取它将它放入缓冲区并且这些缓冲区必须放入队列中。我碰巧在程序中有一些错误而且我不知道究竟在哪里在我的程序中发生错误也不知道为什么?请帮助我,我的逻辑或代码中是否有任何错误以及如何纠正错误。提前致谢

using namespace std;
#define MAX_THREADS 2
#define BUFFER_SIZE 8388608
vector<string>files;
deque<string>bufferq;
CRITICAL_SECTION Readlock;
int count = 0;

DWORD WINAPI ReadThread(LPVOID s);
int main(int argc,char *argv[])
{
    HANDLE ReadT[MAX_THREADS];

    char *filelist[5];
    DWORD threadid;
    filelist[0] = "1.txt";
    filelist[1] = "cloudy.jpg";
    filelist[2] = "connectify.exe";
    filelist[3] = "VMware.exe";
    filelist[4] = "Sherlock.mp4";
    for(int i=0;i<5;i++)
        files.push_back(filelist[i]);

    InitializeCriticalSection(&Readlock);
    long t1 = GetTickCount();
    for(int k = 0; k< MAX_THREADS; k++)
        ReadT[k] = CreateThread(NULL,0,ReadThread,NULL,NULL,&threadid);

    WaitForMultipleObjects(MAX_THREADS,ReadT,TRUE,INFINITE);
    cout << " Time Taken "<< GetTickCount()-t1 << "ms" ;

    system("pause");
    return 0;
}
DWORD WINAPI ReadThread(LPVOID s)
{
    long pending = 0;
    //int freespace = BUFFER_SIZE;
    char *filename = new char[50];
    char fsize[10];
    string file;
    char *buf;
    buf = new char[BUFFER_SIZE];
    long filesize = 0;
    int numfiles = files.size();
    int filled = 0;
    int i = 0;
    FILE *fp;
    char* ptr;
    ptr = buf;

    while(true)
    {
        EnterCriticalSection(&Readlock);
        if(files.empty())
        {
            LeaveCriticalSection(&Readlock);
            break;
        }
        else
        {
            file = files.front();
            files.erase(files.begin());
            LeaveCriticalSection(&Readlock);
        }
        bool buff_full = false;
        buf = ptr;
        int freespace = BUFFER_SIZE;
        memset(buf,0,BUFFER_SIZE);
        if(!buff_full)
        {
            if(pending == 0)
            {
                fp = fopen(file.c_str(),"rb");
                if(!fp)
                    {
                        cout<<"\nNo such file";
                        cout<<files[i];
                        system("pause");
                        return 0;
                    }
                int r1 =fseek(fp, 0L, SEEK_END);
                filesize = ftell(fp);
                int r2 =fseek(fp, 0L, SEEK_SET);
                sprintf(fsize, "%ld", filesize);
                if(freespace >= (strlen(fsize) + strlen(file.c_str()) + 2))
                {
                    count++;
                    memcpy(buf, file.c_str(), strlen(file.c_str())+1);
                    freespace = freespace - strlen(file.c_str()) - 1;
                    buf += strlen(file.c_str()) + 1;
                    memcpy(buf,fsize,strlen(fsize)+1);
                    buf += strlen(fsize) + 1;
                    freespace = freespace - strlen(fsize) - 1;
                    cout<<"Files read is "<<count<<"\n";
                    if(freespace == 0)
                    {
                        buff_full = true;
                        pending = filesize;
                        break;
                    }
                }
                else
                {
                    filled = BUFFER_SIZE - freespace;
                    fclose(fp);
                    break;
                }
                if(freespace >= filesize)
                {
                    fread(buf, 1, filesize, fp);
                    buf += filesize;
                    freespace = freespace - filesize;
                    bufferq.push_back(buf);
                    //cout << "pop"<<bufferq.size();
                    //i++;
                    if(files.empty())
                    {
                        filled = BUFFER_SIZE - freespace;
                        fclose(fp);
                        break;
                    }
                    fclose(fp);
                }
                else
                {
                    fread(buf, 1, freespace, fp);
                    bufferq.push_back(buf);
                    //cout <<"pop "<<bufferq.size();
                    buff_full = true;
                }
            }
            else
            {
                if(freespace >= pending)
                {
                    fread(buf, 1, pending, fp);
                    bufferq.push_back(buf);
                    freespace = freespace - pending;
                    pending = 0;
                    //i++;
                    if(files.empty())
                    {
                        filled = BUFFER_SIZE - freespace;
                        fclose(fp);
                        break;
                    }
                    if(freespace > 0)
                        buf += pending;
                    else
                        buff_full = true;
                    fclose(fp);
                }
                else
                {
                    fread(buf, 1, freespace, fp);
                    bufferq.push_back(buf);
                    cout << bufferq.size();
                    pending = pending - freespace;
                    buff_full = true;
                }
            }
        }
        if(buff_full)
        {
            buf = ptr;
            cout << "popping buffer " << bufferq.size();
            //bufferq.pop_back();
        }
    }
    return 0;
}

1 个答案:

答案 0 :(得分:0)

在大文件出现错误的情况下,我认为这一行可能会导致问题

sprintf(fsize, "%ld", filesize);

fsize是char [10],如果filesize是&gt; = 1,000,000,000,你将用尾随0覆盖fsize数组。这将导致“运行时检查失败#2 - 变量'fsize'周围的堆栈被破坏。 “,正如你写的那样。请检查测试文件的大小。

其中,你在i上循环填充文件,然后你写了:

files.erase(files.begin());
// ...
cout<<"\nNo such file";
cout<<files[i];

files [i]在擦除它们时已指向另一个元素,如果文件在最后一次迭代时为空,则会导致崩溃。

如果不将文件和fsize复制到buq,那么你将它复制到buf是什么?

由于bufferq是可写的并且在线程之间共享,因此对它的访问应该由你选择的lock,critical section保护。

这是我的小代码审查。