File-splitting Function: Uses FILE * - better way with ifstream?

Discussion in 'C++' started by Earl Purple, Jan 13, 2006.

  1. Earl Purple

    Earl Purple Guest

    This is a simple function to split a file into multiple files
    (archives) of a fixed size. The last one will contain any remaining
    bytes.

    Here is the implementation:

    #include <cstdio>
    #include <fstream>
    #include <iomanip>
    #include <vector>

    void split( const std::string & inPath, const std::string& outName,
    size_t bufsize,
    const std::string & ext=".txt" )
    {
    std::vector<char> buf( bufsize, 0 );

    std::FILE* fIn = std::fopen( inPath.c_str(), "r" ); // may
    sometimes want "rb"
    if ( fIn )
    {
    size_t archive=0;

    while ( size_t bytes = std::fread( &buf[0], 1, bufsize, fIn ) )
    {
    std::eek:stringstream oss;
    oss << outName << std::setfill('0') << std::setw( 2 ) <<
    archive << ext;
    std::eek:fstream ofs( oss.str().c_str() );
    if ( ofs )
    {
    ofs.write( &buf[0], bytes );
    }
    else
    {
    std::eek:stringstream osErr;
    osErr << "Failure opening output file " << oss.str();
    throw std::ios_base::failure( osErr.str() );
    }
    ++archive;
    }
    }
    else
    {
    std::eek:stringstream osErr;
    osErr << "Failure opening input file " << inPath;
    throw std::ios_base::failure( osErr.str() );
    }
    }

    It works -you can add a main() to try it. The downside is the use of
    FILE *. I know there are some who will say that there is nothing wrong
    with using FILE * but the purists among us would prefer to use
    ifstream.

    The problem is that the equivalent ifstream.read() function returns the
    stream, not the number of bytes. And if it fails to read the specified
    number, it will enter a fail state. Even then I won't know how many
    bytes were read (Would the buffer still be written?)

    Maybe there is a way to do it using filebuf instead.
    Anybody got a way to replace the FILE * with streams without making the
    code overly complicated?
    Earl Purple, Jan 13, 2006
    #1
    1. Advertising

  2. Earl Purple

    TB Guest

    Earl Purple sade:
    > This is a simple function to split a file into multiple files
    > (archives) of a fixed size. The last one will contain any remaining
    > bytes.
    >
    > Here is the implementation:

    snip
    >
    > It works -you can add a main() to try it. The downside is the use of
    > FILE *. I know there are some who will say that there is nothing wrong
    > with using FILE * but the purists among us would prefer to use
    > ifstream.
    >
    > The problem is that the equivalent ifstream.read() function returns the
    > stream, not the number of bytes. And if it fails to read the specified
    > number, it will enter a fail state. Even then I won't know how many
    > bytes were read (Would the buffer still be written?)


    Look at:

    streamsize std::basic_ifstream::readsome(char_type *s, streamsize n);

    TB
    TB, Jan 13, 2006
    #2
    1. Advertising

  3. Earl Purple

    Earl Purple Guest

    TB wrote:
    >
    > Look at:
    >
    > streamsize std::basic_ifstream::readsome(char_type *s, streamsize n);
    >
    > TB


    Thank you - don't know why I haven't come across that function before.
    Earl Purple, Jan 13, 2006
    #3
  4. Earl Purple wrote:
    [snip]
    > The problem is that the equivalent ifstream.read() function returns the
    > stream, not the number of bytes. And if it fails to read the specified
    > number, it will enter a fail state. Even then I won't know how many
    > bytes were read (Would the buffer still be written?)


    Use ifstream.gcount() to determine how many bytes were read
    with the last call to ifstream::read(...)

    Stephan
    =?iso-8859-1?q?Stephan_Br=F6nnimann?=, Jan 13, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page