How do I read a binary file into a bitset or vector<bool>? The binary file will vary in length. Is there a better container for this? I am new to C++ though experienced as a programmer.
If the file is large, Why should you read once, whole the file into the memory?
You can read a little piece every time. The size is determined with the size in this func:
file.read(buff, size)
When the buff is char's array.
I'm sorry, but You can't simplest read/save vector to file.
for more details see here and here.
And use Google, It's very helpful...
You didn't give too much context of what you're trying to do in your question. But here's one quick & dirty way to do it:
#include <iterator>
#include <fstream>
#include <vector>
#include <assert.h>
using namespace std;
const char *filename = "foo.bar";
int main()
{
vector<bool> v;
ifstream binary_file(filename, ios::binary);
assert(binary_file);
copy(istream_iterator<unsigned char>(binary_file),
istream_iterator<unsigned char>(),
back_insert_iterator< vector<bool> >(v));
}
Reading the zero-byte '\0' character into the vector will be false. Any other bytes read in will be treated as true.
Related
This question already has answers here:
How do I read an entire file into a std::string in C++?
(23 answers)
Closed 4 years ago.
I'm looking for a way to way to read files in C++ I can write files, but here's where I'm stuck at:
ifstream readfile;
readfile.open("C:/Users/Crazy/Desktop/Useless.txt")
I 've seen people do things such as:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
ifstream myReadFile;
myReadFile.open("text.txt");
char output[100];
if (myReadFile.is_open()) {
while (!myReadFile.eof()) {
myReadFile >> output;
cout << output;
}
}
myReadFile.close();
return 0;
}
But in
char output[100];
I want the whole thing read.
Also, I just want to only read it, not to check if it's already open, not to, check for errors. I just want to read the whole thing, and the whole thing only.
If you want to read the entire file into a variable you'll need to:
1. Determine size of file in characters.
2. Use std::vector and declare a vector of that size,
or use the new operator and dynamically allocate a char array.
3. Use ifstream::read to read in the entire file.
4. Close the ifstream.
5. Remember to delete the char buffer.
I recommend using an OS API to determine the file length.
Edit 1: Example
#include <iostream>
#include <fstream>
#include <vector>
std::ifstream my_file("my_data");
my_file.seekg(0, std::ios_base::end); // Seek to end of file.
const unsigned int file_length = my_file.tellg();
my_file.seekg(0);
std::vector<char> file_data(file_length);
my_file.read(&file_data[0], file_length);
I've been struggling with the concept of unformatted I/O. My course textbook doesn't explain it well. It gives the small program but I don't know what is happening here. If someone could explain it to me, I would appreciate it
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
const unsigned int size = 10;
int arr[size];
ifstream infile("small.ppm");
infile.read(reinterpret_cast<char *>(&arr), size * sizeof(arr[0]));
infile.close();
ofstream outfile("newfile.ppm");
outfile.write((char *)&arr, size * sizeof(arr[0]));
outfile.close();
}
What do the read() and write() functions do exactly. I understand that they must
take in (char *, buffer_size) as arguments, but what do the functions themselves do?
Also, once I read in the data with read(), how do I store that data and manipulate it?
Sorry that this is such a long question. I've been struggling with this concept for a while now. Thanks a lot for your help
but what do the functions themselves do?
These are writing/reading the data as a byte by byte copy to/from the binary file.
Also, once I read in the data with read(), how do I store that data and manipulate it?
You already stored a int arr[size];. You can manipulate that data using that int array.
Pitfalls:
If that data was serialized on a different machine, you'll notice endianess issues regarding the machine specific int representation.
Guido Van Rossum demonstrates the simplicity of Python in this article and makes use of this function for buffered reads of a file of unknown length:
def intsfromfile(f):
while True:
a = array.array('i')
a.fromstring(f.read(4000))
if not a:
break
for x in a:
yield x
I need to do the same thing in C++ for speed reasons! I have many files containing sorted lists of unsigned 64 bit integers that I need to merge. I have found this nice piece of code for merging vectors.
I am stuck on how to make an ifstream for a file of unknown length present itself as a vector which can be happily iterated over until the end of the file is reached. Any suggestions? Am I barking up the correct tree with an istreambuf_iterator?
In order to disguise an ifstream (or really, any input stream) in a form that acts like an iterator, you want to use the istream_iterator or the istreambuf_iterator template class. The former is useful for files where the formatting is of concern. For example, a file full of whitespace-delimited integers can be read into the vector's iterator range constructor as follows:
#include <fstream>
#include <vector>
#include <iterator> // needed for istream_iterator
using namespace std;
int main(int argc, char** argv)
{
ifstream infile("my-file.txt");
// It isn't customary to declare these as standalone variables,
// but see below for why it's necessary when working with
// initializing containers.
istream_iterator<int> infile_begin(infile);
istream_iterator<int> infile_end;
vector<int> my_ints(infile_begin, infile_end);
// You can also do stuff with the istream_iterator objects directly:
// Careful! If you run this program as is, this won't work because we
// used up the input stream already with the vector.
int total = 0;
while (infile_begin != infile_end) {
total += *infile_begin;
++infile_begin;
}
return 0;
}
istreambuf_iterator is used to read through files a single character at a time, disregarding the formatting of the input. That is, it will return you all characters, including spaces, newline characters, and so on. Depending on your application, that may be more appropriate.
Note: Scott Meyers explains in Effective STL why the separate variable declarations for istream_iterator are needed above. Normally, you would do something like this:
ifstream infile("my-file.txt");
vector<int> my_ints(istream_iterator<int>(infile), istream_iterator<int>());
However, C++ actually parses the second line in an incredibly bizarre way. It sees it as the declaration of a function named my_ints that takes in two parameters and returns a vector<int>. The first parameter is of type istream_iterator<int> and is named infile (the parantheses are ignored). The second parameter is a function pointer with no name that takes zero arguments (because of the parantheses) and returns an object of type istream_iterator<int>.
Pretty cool, but also pretty aggravating if you're not watching out for it.
EDIT
Here's an example using the istreambuf_iterator to read in a file of 64-bit numbers laid out end-to-end:
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char** argv)
{
ifstream input("my-file.txt");
istreambuf_iterator<char> input_begin(input);
istreambuf_iterator<char> input_end;
// Fill a char vector with input file's contents:
vector<char> char_input(input_begin, input_end);
input.close();
// Convert it to an array of unsigned long with a cast:
unsigned long* converted = reinterpret_cast<unsigned long*>(&char_input[0]);
size_t num_long_elements = char_input.size() * sizeof(char) / sizeof(unsigned long);
// Put that information into a vector:
vector<unsigned long> long_input(converted, converted + num_long_elements);
return 0;
}
Now, I personally rather dislike this solution (using reinterpret_cast, exposing char_input's array), but I'm not familiar enough with istreambuf_iterator to comfortably use one templatized over 64-bit characters, which would make this much easier.
Is there any way to get input from a file one number at a time?
For example I want to store the following integer in an vector of integers since it is so long and can't be held by even a long long int.
12345678901234567900
So how can I read this number from a file so that I can:
vector<int> numbers;
number.push_back(/*>>number goes here<<*/)
I know that the above code isn't really complete but I hope that it explains what I am trying to do.
Also I've tried google and so far it has proved innefective because only tutorials for C are coming up which aren't really helping me all too much.
Thank is advance,
Dan Chevalier
This could be done in a variety of ways, all of them boiling down to converting each char '0'..'9' to the corresponding integer 0..9. Here's how it can be done with a single function call:
#include <string>
#include <iostream>
#include <vector>
#include <iterator>
#include <functional>
#include <algorithm>
int main()
{
std::string s = "12345678901234567900";
std::vector<int> numbers;
transform(s.begin(), s.end(), back_inserter(numbers),
std::bind2nd(std::minus<char>(), '0'));
// output
copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
When reading from a file, you could read the string and transform(), or even transform() directly from istream iterators, if there is nothing else in that file besides your number:
std::ifstream f("test.txt");
std::vector<int> numbers;
transform(std::istream_iterator<char>(f),
std::istream_iterator<char>(),
back_inserter(numbers),
std::bind2nd(std::minus<char>(), '0'));
Off the top of my head this should fill up a character array which you can then iterate through. I realize it's not exactly what you were after but it's my preferred method.
void readfile(char *string)
{
ifstream NumberFile;
NumberFile.open("./Number"); //For a unix file-system
NumberFile >> string;
NumberFile.close();
}
Also, to perform operations on the actual numbers you can use:
CharacterArray[ElementNumber] - '0'
and to get the number when it is small enough to fit in a datatype you add each element of the array multiplied by 10 to the power of its index.
You can read a char at a time with char c; cin.get(c); and convert it to the numeral with c -= '0'. But perhaps you can just read it as a string or use something like BigNum.
Basically my task is having to sort a bunch of strings of variable length ignoring case. I understand there is a function strcasecmp() that compares cstrings, but doesn't work on strings. Right now I'm using getline() for strings so I can just read in the strings one line at a time. I add these to a vector of strings, then convert to cstrings for each call of strcasecmp(). Instead of having to convert each string to a cstring before comparing with strcasecmp(), I was wondering if there was a way I could use cin.getline() for cstrings without having a predefined char array size. Or, would the best solution be to just read in string, convert to cstring, store in vector, then sort?
I assume by "convert to cstring" you mean using the c_str() member of string. If that is the case, in most implementation that isn't really a conversion, it's just an accessor. The difference is only important if you are worried about performance (which it sounds like you are). Internally std::strings are (pretty much always, but technically do not have to be) represented as a "cstring". The class takes care of managing it's size for you, but it's just a dynamically allocated cstring underneath.
So, to directly answer: You have to specify the size of the array when using cin.getline. If you don't want to specify a size, then use getline and std::string. There's nothing wrong with that approach.
C++ is pretty efficient on its own. Unless you have a truly proven need to do otherwise, let it do its thing.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
bool cmp(string a, string b)
{
return(strcasecmp(a.c_str(), b.c_str()) < 0);
}
int main(int argc, char *argv[])
{
vector<string> strArr;
//too lazy to test with getline(cin, str);
strArr.push_back("aaaaa");
strArr.push_back("AAAAA");
strArr.push_back("ababab");
strArr.push_back("bababa");
strArr.push_back("abcabc");
strArr.push_back("cbacba");
strArr.push_back("AbCdEf");
strArr.push_back("aBcDeF");
strArr.push_back(" whatever");
sort(strArr.begin(), strArr.end(), cmp);
copy(strArr.begin(), strArr.end(), ostream_iterator<string>(cout, " \n"));
return(0);
}