0

So I am writing my own custom FTP client for a school project. I managed to get everything to work with the swarming FTP client and am down to one last small part...reading the .part files into the main file. I need to do two things. (1) Get this to read each file and write to the final file properly (2) The command to delete the part files after I am done with each one.

Can someone please help me to fix my concatenate function I wrote below? I thought I had it right to read each file until the EOF and then go on to the next.

In this case *numOfThreads is 17. Ended up with a file of 4742442 bytes instead of 594542592 bytes. Thanks and I am happy to provide any other useful information.

EDIT: Modified code for comment below.

    std::string s = "Fedora-15-x86_64-Live-Desktop.iso";
    std::ofstream out;
    out.open(s.c_str(), std::ios::out);
    for (int i = 0; i < 17; ++i)
    {
            std::ifstream in;
            std::ostringstream convert;
            convert << i;
            std::string t = s + ".part" + convert.str();
            in.open(t.c_str(), std::ios::in | std::ios::binary);
            int size = 32*1024;
            char *tempBuffer = new char[size];
            if (in.good())
            {
                    while (in.read(tempBuffer, size))
                            out.write(tempBuffer, in.gcount());
            }
            delete [] tempBuffer;
            in.close();
    }
    out.close();
    return 0;
MasterGberry
  • 2,612
  • 5
  • 31
  • 54
  • As a notice, you may use in.gcount() to access count of read bytes. Also, you don't free the tempBuffer variable. Everything else looks good to me. Have you checked the file contents? Which file gets truncated and where? – Spook Feb 13 '13 at 05:59
  • `ifstream::read` returns `istream&`, so there seems not to be much point in using it as a condition in while loop. I would use `while (!in.eof())` instead. – Spook Feb 13 '13 at 06:53

1 Answers1

3

Almost everything in your copying loop has problems.

while (!in.eof())

This is broken. Not much more to say than that.

       bzero(tempBuffer, size);

This is fairly harmless, but utterly pointless.

            in.read(tempBuffer, size);

This the "almost" part -- i.e., the one piece that isn't obviously broken.

            out.write(tempBuffer, strlen(tempBuffer));

You don't want to use strlen to determine the length -- it's intended only for NUL-terminated (C-style) strings. If (as is apparently the case) the data you read may contain zero-bytes (rather than using zero-bytes only to signal the end of a string), this will simply produce the wrong size.

What you normally want to do is a loop something like:

while (read(some_amount) == succeeded)
    write(amount that was read);

In C++ that will typically be something like:

while (infile.read(buffer, buffer_size))
    outfile.write(buffer, infile.gcount());

It's probably also worth noting that since you're allocating memory for the buffer using new, but never using delete, your function is leaking memory. Probably better to do without new for this -- an array or vector would be obvious alternatives here.

Edit: as for why while (infile.read(...)) works, the read returns a reference to the stream. The stream in turn provides a conversion to bool (in C++11) or void * (in C++03) that can be interpreted as a Boolean. That conversion operator returns the state of the stream, so if reading failed, it will be interpreted as false, but as long as it succeeded, it will be interpreted as true.

Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035
  • Whoops on the memory leak. Ty for that extra point, been a long day. – MasterGberry Feb 13 '13 at 06:04
  • So I made the changes as you suggested, and got further than before....still a bit off though. I eneded up with `594378752` bytes instead of `594542592` bytes, missing `163840` bytes in total. I modified my code up above with the latest version of what you had suggested. – MasterGberry Feb 13 '13 at 06:13
  • 1
    `istream::read` returns `istream&`, what's the point of `while (infile.read())` ? One should use `infile.eof()` instead. – Spook Feb 13 '13 at 06:45
  • 1
    @Spook: Please see the [previous question](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) devoted to exactly that. I'd particularly recommend Nawaz's answer. – Jerry Coffin Feb 13 '13 at 16:09
  • Fair enough, I stand corrected. However, in this situation using eof seems to be a good idea anyway, because `infile.gcount()` will return 0 in case you reached *exactly* the end of stream, isn't it? – Spook Feb 13 '13 at 20:22
  • Also, I cannot remove the downvote until you edit the post - strange SO restriction. Adding short note about stream being converted to bool might be a good idea though for those like me ;) – Spook Feb 13 '13 at 20:23