CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    1,569

    Checking for empty .txt file

    Code:
    #include <fstream>
    #include <iterator>
    #include <algorithm>
    #include <string>
    
    // Reads data from a file.
    //  - Requires that Object has an overloaded >> operator.
    //  - Returns a Container of Objects.
    //  - Returns early if file is empty.
    template <typename Object, typename Container>
    Container read_data(std::istream& file)
    {
      Container v;
    
      if(file.eof())
      { // Empty; return early.
        return v;
      }
    
      std::copy(
        std::istream_iterator<Object>(file),
        std::istream_iterator<Object>(),
        std::back_inserter(v));
    
      return v;
    }
    Hey. I've got this function.. I'm trying to test if the file passed in is completely empty... if it is, I return early for certain reasons. I'm just wondering how I can do this in the most elegant way... what I have above (in bold) doesn't work. I debugged it and the if statement body never gets reached.

    Cheers.
    Good judgment is gained from experience. Experience is gained from bad judgment.
    Cosy Little Game | SDL | GM script | VLD | Syntax Hlt | Can you help me with my homework assignment?

  2. #2
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Re: Checking for empty .txt file

    Quote Originally Posted by Mybowlcut
    Code:
    #include <fstream>
    #include <iterator>
    #include <algorithm>
    #include <string>
     
    // Reads data from a file.
    // - Requires that Object has an overloaded >> operator.
    // - Returns a Container of Objects.
    // - Returns early if file is empty.
    template <typename Object, typename Container>
    Container read_data(std::istream& file)
    {
    Container v;
     
    if(file.eof())
    { // Empty; return early.
    return v;
    }
     
    std::copy(
    std::istream_iterator<Object>(file),
    std::istream_iterator<Object>(),
    std::back_inserter(v));
     
    return v;
    }
    Hey. I've got this function.. I'm trying to test if the file passed in is completely empty... if it is, I return early for certain reasons. I'm just wondering how I can do this in the most elegant way... what I have above (in bold) doesn't work. I debugged it and the if statement body never gets reached.

    Cheers.
    I think You dont need to check if file is empty.
    I think you sould use insert member function of the container.
    Code:
    v.insert( std::istream_iterator<Object>(file), std::istream_iterator<Object>());
    Dont forget to rate my post if you find it useful.

  3. #3
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    1,569

    Re: Checking for empty .txt file

    I took the read_data idea from Paul McKenzie, so I don't really understand the internals of copy and the istream_iterators. It works, so I use it, but I have a situation where the >> operator is being called when the file is empty and I don't want this to happen. I'm guessing it's due to the workings of copy... Would insert prevent the >> operator being called when the file is empty? If not I still need a solution.
    Good judgment is gained from experience. Experience is gained from bad judgment.
    Cosy Little Game | SDL | GM script | VLD | Syntax Hlt | Can you help me with my homework assignment?

  4. #4
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Checking for empty .txt file

    One way to tell the size is to use seekg and tellg:

    Something like this:

    Code:
    size_t FileSize(std::istream& stream)
    {
        stream.seekg(0, std::ios::end); // Move to end of the file
    
        size_t result = stream.tellg(); // Ask where we are now.
    
        stream.seekg(0, std::ios::beg); // Move back to beginning of file.
    
        return result;
    }
    See also:
    http://www.cplusplus.com/reference/i...eam/seekg.html
    http://www.cplusplus.com/reference/i...eam/tellg.html
    Last edited by Zaccheus; February 20th, 2008 at 04:03 AM.
    My hobby projects:
    www.rclsoftware.org.uk

  5. #5
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    Re: Checking for empty .txt file

    Originally posted by MyBowlcut:
    I took the read_data idea from Paul McKenzie, so I don't really understand the internals of copy and the istream_iterators. It works, so I use it...
    The arguments to std::copy() are
    1. An input iterator that addresses the starting position in the source
    from which you want to copy
    2. Another input iterator that addresses the ending position in the source
    3. An output iterator that addresses the starting position in the
    destination to which you want to copy.

    Code:
    std::copy(
        std::istream_iterator<Object>(file),
        std::istream_iterator<Object>(),
        std::back_inserter(v));
    Now, what we are passing to std::copy are :
    1. istream_iterator that is initialized to the stream from which we want to
    read. That's the starting position in our source.
    2. A default istream_iterator that initializes to end-of-stream by default.
    That's the end position in our source. So, the objects will be copied from
    the input file until end of file is reached. You don't need to explicitly
    check for end-of-file.
    3. Makes an iterator that can insert elements at the back of the container. Using this iterator requires that the container have a push_back() method which means that we can only use deques, lists or vectors.

    That's all there is to it.
    Some sample code...See if this works. Also create an empty text file - Test.txt in your source directory.
    Code:
    #include <iostream>
    #include <fstream>
    #include <iterator>
    #include <algorithm>
    #include <string>
    #include <vector>
     
    // Reads data from a file.
    // - Requires that Object has an overloaded >> operator.
    // - Returns a Container of Objects.
    // - Returns early if file is empty.
    template <typename Object, typename Container>
    Container ReadData(std::istream& file)
    {
        Container v;
        
        /* 
        //We don't need this.
        if(file.eof())
        {   // Empty; return early.
            return v;
        }
        */
             
        std::copy(
        std::istream_iterator<Object>(file),
        std::istream_iterator<Object>(),
        std::back_inserter(v));    
         
        return v;
    }
    
    int main()
    {
        std::ifstream file("Test.txt");
        std::vector<char> vFile;
        
        vFile = ReadData<char, std::vector<char> >(file);
        
        for(int i = 0; i < vFile.size(); ++i)
            std::cout<<vFile[i];
        
        file.close();
        return 0;
    }
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  6. #6
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Re: Checking for empty .txt file

    std::copy is allright..

    But I guess using container.assign(it1, it2); is better...

    Rule of thumb is: Any action which is done with pair of iterator is better than the one achieved with one iterator..

    With std::copy approach you will effectively be calling push_back which will do many reallocation and one function call for every element being added in the container..

    While when you use container::assign() with pair of iterator.

    I think the required space will already be created and no re-allocation will happen. Moreover you will have only one function call.

    so I think its better to use container.assign(it1, it2) or container.insert(container.begin(),it1,it2); than copy here...

    Correct me if I am wrong..
    Dont forget to rate my post if you find it useful.

  7. #7
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Checking for empty .txt file

    I don't think insert can determine the number of elements from an istream_iterator (note also that the second iterator is simply default constructed).
    My hobby projects:
    www.rclsoftware.org.uk

  8. #8
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Re: Checking for empty .txt file

    Quote Originally Posted by Zaccheus
    I don't think insert can determine the number of elements from an istream_iterator (note also that the second iterator is simply default constructed).
    Assign and Insert both take input iterator and istream_iterator is very much input iterator.

    When given a pair of iterator to assign of insert generally it creates memory large enough to hold the range.

    yes you may be right..But the question remains: Then how insert or assign works?
    Dont forget to rate my post if you find it useful.

  9. #9
    Join Date
    Nov 2006
    Location
    Australia
    Posts
    1,569

    Re: Checking for empty .txt file

    Quote Originally Posted by angelorohit
    The arguments to std::copy() are
    1. An input iterator that addresses the starting position in the source
    from which you want to copy
    2. Another input iterator that addresses the ending position in the source
    3. An output iterator that addresses the starting position in the
    destination to which you want to copy.

    Code:
    std::copy(
        std::istream_iterator<Object>(file),
        std::istream_iterator<Object>(),
        std::back_inserter(v));
    Now, what we are passing to std::copy are :
    1. istream_iterator that is initialized to the stream from which we want to
    read. That's the starting position in our source.
    2. A default istream_iterator that initializes to end-of-stream by default.
    That's the end position in our source. So, the objects will be copied from
    the input file until end of file is reached. You don't need to explicitly
    check for end-of-file.
    3. Makes an iterator that can insert elements at the back of the container. Using this iterator requires that the container have a push_back() method which means that we can only use deques, lists or vectors.

    That's all there is to it.
    Some sample code...See if this works. Also create an empty text file - Test.txt in your source directory.
    Code:
    #include <iostream>
    #include <fstream>
    #include <iterator>
    #include <algorithm>
    #include <string>
    #include <vector>
     
    // Reads data from a file.
    // - Requires that Object has an overloaded >> operator.
    // - Returns a Container of Objects.
    // - Returns early if file is empty.
    template <typename Object, typename Container>
    Container ReadData(std::istream& file)
    {
        Container v;
        
        /* 
        //We don't need this.
        if(file.eof())
        {   // Empty; return early.
            return v;
        }
        */
             
        std::copy(
        std::istream_iterator<Object>(file),
        std::istream_iterator<Object>(),
        std::back_inserter(v));    
         
        return v;
    }
    
    int main()
    {
        std::ifstream file("Test.txt");
        std::vector<char> vFile;
        
        vFile = ReadData<char, std::vector<char> >(file);
        
        for(int i = 0; i < vFile.size(); ++i)
            std::cout<<vFile[i];
        
        file.close();
        return 0;
    }
    Thanks for that explanation, angelorohit.

    In this case I do need to check the size of the file before proceeding, though.

    Thanks, Zaccheus. That will do just fine.
    Good judgment is gained from experience. Experience is gained from bad judgment.
    Cosy Little Game | SDL | GM script | VLD | Syntax Hlt | Can you help me with my homework assignment?

  10. #10
    Join Date
    Oct 2006
    Location
    Singapore
    Posts
    346

    Re: Checking for empty .txt file

    Originally posted by code_carnage:
    When given a pair of iterator to assign of insert generally it creates memory large enough to hold the range.
    What the insert() of a particular container does depends on a number of things. In this case, since our source iterator is an input interator, it will not pre-allocate anything, simply because it doesn't know how many objects it has to insert. As it reads each object from the file, it will make allocations accordingly. Hence, in this case, insert() is no better off than std::copy(). Of course, I am only talking about the Microsoft compiler's implementation of STL. Other compilers may do things differently. From what I've seen, some overloaded definitions of insert() even end up invoking std::copy().
    Believe in your Dreams, Work for what you Believe in.
    My thoughts? Angelo's Stuff
    Some fun things I've done: RayWatch, QuickFeed, ACSVParser

    @ngelo

  11. #11
    Join Date
    May 2007
    Location
    Bangalore India
    Posts
    262

    Re: Checking for empty .txt file

    Yes.
    Dont forget to rate my post if you find it useful.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured