I want to copy all the files from one directory to another using the fread() and fwrite()-statements.
Some of these files are rather large in size, and that's why I want to calculate who long the transfer will take.
(Later I will use this information to show a progress bar containing remaining transfer time, percent data transferred so far and (possibly) the actual transfer speed).

The problem is:
When I try to do a full transfer of the biggest file in the list (the one with index 0 in the fdata-struct) I find that the transfer time is much higher than the calculated time. I think this is strange since I'm using the filecopy routine in both cases..*

<Background information>:

First I obtain a filelist from the source directory (srcdir) using opendir() and readdir(). The information is put in the struct finfo named "fcont".

struct finfo {
 string filename;
 unsigned long fsize;
 float ttime;
 bool operator() (finfo i, finfo j)
    {
        if(i.fsize == j.fsize)
         return i.filename < j.filename;
     return (i.fsize > j.fsize);}

} fstruct;

vector<finfo> fdata;

// ==================
// == Main program ==
// ==================

    const string INFO1 = "Error using opendir(). Terminating..";

    FILE *iFile, *oFile;
    DIR *pdir;
    string srcdir;
    finfo fcont;


    srcdir = argv[1]; 

    pdir = opendir(srcdir.c_str());

    if (!pdir)
    {
        cout << INFO1 << endl;
        exit(1);
    }

            while ((pent=readdir(pdir)))
            {
              if (pent->d_name[0] != '.')
                {
                  fcont.filename = pent->d_name;
                  iFile = openfile(srcdir + "/" + pent->d_name,"read");
                  fcont.fsize = filesize(iFile,"TRUE");   
                  fdata.push_back(fcont);
                }
            }
            cout << endl;

    closedir(pdir);

Then the struct fdata is sorted by file size and by file name if the file size is equal.

sort(fdata.begin(),fdata.end(),fstruct);

The next step is to calculate the total number of buffers to be transferred for to copy the entire file.

// ======================================================
// == Calculating number of buffers to be transferred. ==
// ======================================================

       AntBuff = fdata[0].fsize / BUFSIZE;

In this case I'm using:
DELTA = 4
DELTABUFF = 10000
BUFSIZE = 8192

To calculate the average transfer time in seconds I do DELTA iterations each containing reading and writing
DELTABUFF number of buffers with BUFSIZE while I measure the elapsed time for these read and write operations.
For each iteration I close both the source and destination file and deletes the destination file.

The average transfer time is the sum of transfer times divided with DELTA.

At last I calculate the transfer time for each file in the fdata struct by calculating ((fsize/BUFSIZE)/SnittBuff).

// ========================================================
// == Calculating average time for transferring buffers  ==
// ========================================================

       for (i=1; i <= DELTA; i++)
         {
          iFile = openfile(srcfile,"read");
          oFile = openfile(dstfile,"write");

// == Start time ==
        gettimeofday(&tim,NULL);
        t1 = tim.tv_sec + (tim.tv_usec/1000000.0);

// == Reading source file and writing to destination file DELTABUFF number of buffers with size BUFSIZE ==
            for (iSpeed = 1;iSpeed <= DELTABUFF;iSpeed++)
            {
              retval = filecopy(iFile,oFile);
            }

// == End time ==
          gettimeofday(&tim,NULL);
          t2 = tim.tv_sec + (tim.tv_usec/1000000.0);

// == Calculating number of buffers transferred pr.second ==
          CalcAntBuff = DELTABUFF/(t2-t1);

// == Closing source- and destination file ==
          fclose(iFile);
          fclose(oFile);

// == Deleting destination file ==
          if( remove(dstfile.c_str()) != 0 ) {
           string str = "Error deleting file " + dstfile;
           perror( str.c_str());
          }
// == Total sum of number of buffers transferred pr. second
           SumBuff = SumBuff + CalcAntBuff;
         }

// == Average number of buffers transferred pr. second.
           SnittBuff = SumBuff / DELTA;

// ==========================================
// == Calculating transfer time in seconds ==
// ==========================================
      for (count=0;count<=fdata.size()-1;count++) {
         if (fdata[count].fsize == 0) {
          fdata[count].ttime = 0;
         }
         else
          {
            AntBuff = fdata[count].fsize / BUFSIZE;
            fdata[count].ttime = AntBuff / SnittBuff;
          }
      }

But the problem is:
When I try to do a full transfer of the biggest file in the list (the one with index 0 in the fdata-struct) I find that the transfer time is much higher than the calculated time. I think this is strange since I'm using the filecopy routine in both cases..

To transfer (copy) the complete file I use the following code:

    iFile = openfile(srcfile,"read");
    oFile = openfile(dstfile,"write");

    gettimeofday(&tim,NULL);
    t1 = tim.tv_sec + (tim.tv_usec/1000000.0);

    while (size !=0) {
          retval = filecopy(iFile,oFile);
    }

    gettimeofday(&tim,NULL);
    t2 = tim.tv_sec + (tim.tv_usec/1000000.0);

    fclose(oFile);
    fclose(iFile);

The openfile, filesize and filecopy routines:

FILE * openfile(string filename,string access){
    FILE *hFile;

    if (access == "read")
    {
        hFile = fopen(filename.c_str(),"rb");
    }
    else if (access == "write")
    {
        hFile = fopen(filename.c_str(),"wb");
    }

    if (errno == 0) {
     return hFile;
    }
    else
     exit(0);
} 

long filesize(FILE *iFile, bool closefile) {

    struct stat buffer;
    long fssize;
    int fs;

        fs = fileno(iFile);
        fstat(fs,&buffer);
        fssize = buffer.st_size;

    if (closefile) {
     fclose(iFile);
    }

    return fssize;    
}


   int filecopy(FILE *iFile, FILE *oFile){

      size = fread(buf,1,BUFSIZE,iFile);
      fwrite(buf,1,size,oFile);

    return (0);
}

Recommended Answers

All 2 Replies

Nobody really gets this correct. Microsoft certainly doesn't get it right, and Linux engineers are not much better. There are too many factors such as system load, I/O loads, disc read/write speeds, is the source file on one disc and the target on another or the same disc? What are their speeds, buffer sizes, etc. You can get the actual size easily enough, and let your progress bar show the actual percentage of the file that has transferred. After some has been moved, you can start estimating how long it will take and show that in a window with the progress bar. That is how most do it.

The problem is that I want to show the progress bar for example with 5 seconds intervals. But how can I achieve that ?
My solution is:
1) Calculate the time it takes to read/write one buffer in seconds.
2) Multiply this result with 5 (5 seconds). It gives me the number of buffers transferred in 5 seconds.
3) Make a loop transferring the number of buffers from 2) before calculating and displaying the progress bar and then continuing the loop and so on..

In my example both the source and destination directory is on the same local disk on the same system so the disc read/write speed should be the same, the system load should be the same and (for what I know) the I/O load should be the same. But when I compare the calculated transfer time with the actual transfer time I find that the results could be 6 seconds (calculated) and 37 seconds(!) actual transfer time. And THAT is very strange..

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.