|
-
February 20th, 2008, 01:48 AM
#1
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.
-
February 20th, 2008, 02:11 AM
#2
Re: Checking for empty .txt file
 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.
-
February 20th, 2008, 02:23 AM
#3
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.
-
February 20th, 2008, 03:58 AM
#4
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.
-
February 20th, 2008, 04:08 AM
#5
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;
}
-
February 20th, 2008, 04:17 AM
#6
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.
-
February 20th, 2008, 05:04 AM
#7
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).
-
February 20th, 2008, 05:22 AM
#8
Re: Checking for empty .txt file
 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.
-
February 20th, 2008, 06:14 AM
#9
Re: Checking for empty .txt file
 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.
-
February 20th, 2008, 06:27 AM
#10
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().
-
February 20th, 2008, 06:32 AM
#11
Re: Checking for empty .txt file
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|