Set integer variable through file read - c++

I know how to pass in strings from a text file. In a previous project I read in strings and then tested them on either being "t" or "f", which the result of would set a variable to true or false.
Now I am wondering if it is efficiently possible to read numbers from a text file and pass them into an int? All I can think of is checking for the string "1" and returning 1 in a function, but that would have to be done for every possible integer I could expect in my program, which is not an effective solution.
For context, I am trying to make a save system for a game, and ints/floats that are read in would be variables such as player health, how much of an item they have, etc.

If you already know how to read a string str from a text file, reading numbers is not that difficult: jsut read the string as you did and use stoi() to convert the string into an int, or stof() into float.
int i; double d;
i=stroi(str); d=strod(str2);
Another technique is to use file streams to read or write from a file exactly as you would do from cin and cout:
ifstream file("mytext.txt");
file>>i>>d;
The previous method doesn't care so much about lines. So still another technique is to read a string, convert it into a string stream and use the stringstream as you would with cin:
if (getline(file, str)){ // read a full line
stringstream sst(str);
sst>>i>>d;
}

Using std::fstream. You can open a file, and stream input or output based on how you opened the file.
Example:
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
// Pretend we are passed the file location as a command-line argument to our program:
std::fstream file { argv[1], std::ios::in };
if (file.is_open())
{
int value;
file >> value;
std::cout << value << std::endl;
}
else
{
std::cout << "Could not open file " << argv[1] << std::endl;
}
}
Provided that the information is correctly formatted in the file, this should work.
I didn't run it, so there might be syntax errors, but the basics are there. Check out cppreference for some help, they will have further examples.

Related

using ios::ate over-write data

My task is to write in a precise position into file.txt with C++
And because my file is static ( it will not be changed) I decided to count the position of curseur where I have to write. ( I know it isn't the best idea to di this)
This is my file and I have to write after '=' :
It is clear that I want to over-write "null;"
But I don't understand why "int main" in the otehr line is also over-writed! Have a look to the following please to undersatnd my problem:
My questions are the following:
How Can I avoid this?
Have you other idea to achieve the goal as described above ?
The is my attempt :
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream monFlux("client.txt",ios::in | ios::ate);
if(monFlux)
{
monFlux.seekp(61, ios::beg);
int position = monFlux.tellp();
monFlux<< "DECryptBlockWithPCRYPT(d);";
}
else
{
cout << "ERROR" << endl;
}
system("pause");
return 0;
}
First, it looks like you're opening an output stream for reading (ios::in) is that correct?
I don't think you can insert characters the way you describe.
Your approach is more like a human would do it in a text editor. The stream object on the other side just gives you access to the bytes on the disk. It has no "select and replace" text function.
I think this approach could work:
Open an input stream for reading the file and an output stream for writing one.
Stream the first N characters directly to the output stream.
Skip the "null" and insert your replacement string.
Stream the rest of the input file into the output stream.
On success, replace the original file with the new one.

Decoding / Encloding Text File using Stack Library - Can't Encode Large Files C++

I am working on a program that can encode and then decode text in C++. I am using the stack library. The way the program works is that it first asks you for a cypher key, which you put in manually. It then asks for the file name, which is a text file. If it is a normal txt file, it encodes the message to a new file and adds a .iia files extension. If the text file already has a .iia file extension, then it decodes the message, as long as the cypher key is the same as the one used to encode it.
My program does encode and decode, but how many characters it decodes is determined by temp.size() % cypher.length() that is in the while loop in the readFileEncode() function. I think this is what is keeping the entire file from being encoded and then decoded correctly. Another words, the ending file after it has been decoded from say "example.txt.iia" back to "example.txt" is missing a large portion of the text from the original "example.txt" file. I tried just cypher.length() but of course that does not encode or decode anything then. The entire process is determined by that argument for the decoding and encoding.
I cannot seem to find out the exact logic for this to encode and decode all the characters in any size file. Here is the following code for the function that does the decoding and encoding:
EDIT: Using WhozCraig's code that he edited for me:
void readFileEncode(string fileName, stack<char> &text, string cypher)
{
std::ifstream file(fileName, std::ios::in|std::ios::binary);
stack<char> temp;
char ch;
while (file.get(ch))
temp.push(ch ^ cypher[temp.size() % cypher.length()]);
while (!temp.empty())
{
text.push(temp.top());
temp.pop();
}
}
EDIT: A stack is required. I am going to implement my own stack class, but I am trying to get this to work first with the stack library. Also, if there is a better way of implementing this, please let me know. Otherwise, I believe that there is not much wrong with this except to get it to go through the loop to encode and decode the entire file. I am just unsure as to why it stops at, say 20 characters sometimes, or ten characters. I know it has to do with how long the cypher is too, so I believe it is in the % (mod). Just not sure how to rewrite.
EDIT: Ok, tried WhozCraig's solution and I don't get the desired output, so the error now must be in my main. Here is my code for the main:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cctype>
#include <stack>
using namespace std;
void readFileEncode(string fileName, stack<char> &text, string cypher);
int main()
{
stack<char> text; // allows me to use stack from standard library
string cypher;
string inputFileName;
string outputFileName;
int position;
cout << "Enter a cypher code" << endl;
cin >> cypher;
cout << "Enter the name of the input file" << endl;
cin >> inputFileName;
position = inputFileName.find(".iia");//checks to see if the input file has the iia extension
if (position > 1){
outputFileName = inputFileName;
outputFileName.erase(position, position + 3);// if input file has the .iia extension it is erased
}
else
//outputFileName.erase(position, position + 3);// remove the .txt extension and
outputFileName = inputFileName + ".iia";// add the .iia extension to file if it does not have it
cout << "Here is the new name of the inputfile " << outputFileName << endl; // shows you that it did actually put the .iia on or erase it depending on the situation
system("pause");
readFileEncode(inputFileName, text, cypher); //calls function
std::ofstream file(outputFileName); // calling function
while (text.size()){// goes through text file
file << text.top();
text.pop(); //clears pop
}
system("pause");
}
Basically, I am reading .txt file to encrypt and then put a .iia file extension on the filename. Then I go back through, enter the file back with the .iia extension to decode it back. When I decode it back it is gibberish after about the first ten words.
#WhozCraig Does it matter what white space, newlines, or punctuation is in the file? Maybe with the full solution here you can direct me at what is wrong.
just for information: never read file char by char it will take you hours to finish 100Mb.
read at least 512 byte(in my case i read directly 1 or 2Mb ==> store in char * and then process).
If I understand what you're trying to do correctly, you want the entire file rotationally XOR'd with the chars in the cipher key. If that is the case, you can probably address your immediate error by simply doing this:
void readFileEncode(string fileName, stack<char> &text, string cypher)
{
std::ifstream file(fileName, std::ios::in|std::ios::binary);
stack<char> temp;
char ch;
while (file.get(ch))
temp.push(ch ^ cypher[temp.size() % cypher.length()]);
while (!temp.empty())
{
text.push(temp.top());
temp.pop();
}
}
The most notable changes are
Opening the file in binary-mode using std::ios::in|std::ios::binary for the open-mode. this will eliminate the need to invoke the noskipws manipulator (which is usually a function call) for every character extracted.
Using file.get(ch) to extract the next character. The member will pull the next char form the file buffer directly if one is available, otherwise load the next buffer and try again.
Alternative
A character by character approach is going to be expensive any way you slice it. That this is going through a stack<>, which will be backed by a vector or deque isn't going to do you any favors. That it is going through two of them just compounds the agony. You may as well load the whole file in one shot, compute all the XOR's directly, then push them on to you stack via a reverse iterator:
void readFileEncode
(
const std::string& fileName,
std::stack<char> &text,
const std::string& cypher
)
{
std::ifstream file(fileName, std::ios::in|std::ios::binary);
// retrieve file size
file.seekg(0, std::ios::end);
std::istream::pos_type pos = file.tellg();
file.seekg(0, std::ios::beg);
// early exit on zero-length file.
if (pos == 0)
return;
// make space for a full read
std::vector<char> temp;
temp.resize(static_cast<size_t>(pos));
file.read(temp.data(), pos);
size_t c_len = cypher.length();
for (size_t i=0; i<pos; ++i)
temp[i] ^= cypher[i % c_len];
for (auto it=temp.rbegin(); it!=temp.rend(); ++it)
text.push(*it);
}
You still get your stack on the caller-side, but I think you'll be considerably happier with the performance.

Efficiently read CSV file with optional columns

I'm trying to write a program that reads in a CSV file (no need to worry about escaping anything, it's strictly formatted with no quotes) but any numeric item with a value of 0 is instead just left blank. So a normal line would look like:
12,string1,string2,3,,,string3,4.5
instead of
12,string1,string2,3,0,0,string3,4.5
I have some working code using vectors but it's way too slow.
int main(int argc, char** argv)
{
string filename("path\\to\\file.csv");
string outname("path\\to\\outfile.csv");
ifstream infile(filename.c_str());
if(!infile)
{
cerr << "Couldn't open file " << filename.c_str();
return 1;
}
vector<vector<string>> records;
string line;
while( getline(infile, line) )
{
vector<string> row;
string item;
istringstream ss(line);
while(getline(ss, item, ','))
{
row.push_back(item);
}
records.push_back(row);
}
return 0;
}
Is it possible to overload operator<< of ostream similar to How to use C++ to read in a .csv file and output in another form? when fields can be blank?
Would that improve the performance?
Or is there anything else I can do to get this to run faster?
Thanks
The time spent reading the string data from the file is greater than the time spent parsing it. You won't make significant time savings in the parsing of the string.
To make your program run faster, read bigger "chunks" into memory; get more data per read. Research on memory mapped files.
One alternative way to handle this to get better performance is to read the whole file into a buffer. Then go through the buffer and set pointers to where the values start, if you find a , or end of line put in a \0.
e.g. https://code.google.com/p/csv-routine/

Reading a string from a file in C++

I'm trying to store strings directly into a file to be read later in C++ (basically for the full scope I'm trying to store an object array with string variables in a file, and those string variables will be read through something like object[0].string). However, everytime I try to read the string variables the system gives me a jumbled up error. The following codes are a basic part of what I'm trying.
#include <iostream>
#include <fstream>
using namespace std;
/*
//this is run first to create the file and store the string
int main(){
string reed;
reed = "sees";
ofstream ofs("filrsee.txt", ios::out|ios::binary);
ofs.write(reinterpret_cast<char*>(&reed), sizeof(reed));
ofs.close();
}*/
//this is run after that to open the file and read the string
int main(){
string ghhh;
ifstream ifs("filrsee.txt", ios::in|ios::binary);
ifs.read(reinterpret_cast<char*>(&ghhh), sizeof(ghhh));
cout<<ghhh;
ifs.close();
return 0;
}
The second part is where things go haywire when I try to read it.
Sorry if it's been asked before, I've taken a look around for similar questions but most of them are a bit different from what I'm trying to do or I don't really understand what they're trying to do (still quite new to this).
What am I doing wrong?
You are reading from a file and trying to put the data in the string structure itself, overwriting it, which is plain wrong.
As it can be verified at http://www.cplusplus.com/reference/iostream/istream/read/ , the types you used were wrong, and you know it because you had to force the std::string into a char * using a reinterpret_cast.
C++ Hint: using a reinterpret_cast in C++ is (almost) always a sign you did something wrong.
Why is it so complicated to read a file?
A long time ago, reading a file was easy. In some Basic-like language, you used the function LOAD, and voilĂ !, you had your file.
So why can't we do it now?
Because you don't know what's in a file.
It could be a string.
It could be a serialized array of structs with raw data dumped from memory.
It could even be a live stream, that is, a file which is appended continuously (a log file, the stdin, whatever).
You could want to read the data word by word
... or line by line...
Or the file is so large it doesn't fit in a string, so you want to read it by parts.
etc..
The more generic solution is to read the file (thus, in C++, a fstream), byte per byte using the function get (see http://www.cplusplus.com/reference/iostream/istream/get/), and do yourself the operation to transform it into the type you expect, and stopping at EOF.
The std::isteam interface have all the functions you need to read the file in different ways (see http://www.cplusplus.com/reference/iostream/istream/), and even then, there is an additional non-member function for the std::string to read a file until a delimiter is found (usually "\n", but it could be anything, see http://www.cplusplus.com/reference/string/getline/)
But I want a "load" function for a std::string!!!
Ok, I get it.
We assume that what you put in the file is the content of a std::string, but keeping it compatible with a C-style string, that is, the \0 character marks the end of the string (if not, we would need to load the file until reaching the EOF).
And we assume you want the whole file content fully loaded once the function loadFile returns.
So, here's the loadFile function:
#include <iostream>
#include <fstream>
#include <string>
bool loadFile(const std::string & p_name, std::string & p_content)
{
// We create the file object, saying I want to read it
std::fstream file(p_name.c_str(), std::fstream::in) ;
// We verify if the file was successfully opened
if(file.is_open())
{
// We use the standard getline function to read the file into
// a std::string, stoping only at "\0"
std::getline(file, p_content, '\0') ;
// We return the success of the operation
return ! file.bad() ;
}
// The file was not successfully opened, so returning false
return false ;
}
If you are using a C++11 enabled compiler, you can add this overloaded function, which will cost you nothing (while in C++03, baring optimizations, it could have cost you a temporary object):
std::string loadFile(const std::string & p_name)
{
std::string content ;
loadFile(p_name, content) ;
return content ;
}
Now, for completeness' sake, I wrote the corresponding saveFile function:
bool saveFile(const std::string & p_name, const std::string & p_content)
{
std::fstream file(p_name.c_str(), std::fstream::out) ;
if(file.is_open())
{
file.write(p_content.c_str(), p_content.length()) ;
return ! file.bad() ;
}
return false ;
}
And here, the "main" I used to test those functions:
int main()
{
const std::string name(".//myFile.txt") ;
const std::string content("AAA BBB CCC\nDDD EEE FFF\n\n") ;
{
const bool success = saveFile(name, content) ;
std::cout << "saveFile(\"" << name << "\", \"" << content << "\")\n\n"
<< "result is: " << success << "\n" ;
}
{
std::string myContent ;
const bool success = loadFile(name, myContent) ;
std::cout << "loadFile(\"" << name << "\", \"" << content << "\")\n\n"
<< "result is: " << success << "\n"
<< "content is: [" << myContent << "]\n"
<< "content ok is: " << (myContent == content)<< "\n" ;
}
}
More?
If you want to do more than that, then you will need to explore the C++ IOStreams library API, at http://www.cplusplus.com/reference/iostream/
You can't use std::istream::read() to read into a std::string object. What you could do is to determine the size of the file, create a string of suitable size, and read the data into the string's character array:
std::string str;
std::ifstream file("whatever");
std::string::size_type size = determine_size_of(file);
str.resize(size);
file.read(&str[0], size);
The tricky bit is determining the size the string should have. Given that the character sequence may get translated while reading, e.g., because line end sequences are transformed, this pretty much amounts to reading the string in the general case. Thus, I would recommend against doing it this way. Instead, I would read the string using something like this:
std::string str;
std::ifstream file("whatever");
if (std::getline(file, str, '\0')) {
...
}
This works OK for text strings and is about as fast as it gets on most systems. If the file can contain null characters, e.g., because it contains binary data, this doesn't quite work. If this is the case, I'd use an intermediate std::ostringstream:
std::ostringstream out;
std::ifstream file("whatever");
out << file.rdbuf();
std::string str = out.str();
A string object is not a mere char array, the line
ifs.read(reinterpret_cast<char*>(&ghhh), sizeof(ghhh));
is probably the root of your problems.
try applying the following changes:
char[BUFF_LEN] ghhh;
....
ifs.read(ghhh, BUFF_LEN);

How do you open a file in C++?

I want to open a file for reading, the C++ way. I need to be able to do it for:
text files, which would involve some sort of read line function.
binary files, which would provide a way to read raw data into a char* buffer.
You need to use an ifstream if you just want to read (use an ofstream to write, or an fstream for both).
To open a file in text mode, do the following:
ifstream in("filename.ext", ios_base::in); // the in flag is optional
To open a file in binary mode, you just need to add the "binary" flag.
ifstream in2("filename2.ext", ios_base::in | ios_base::binary );
Use the ifstream.read() function to read a block of characters (in binary or text mode). Use the getline() function (it's global) to read an entire line.
There are three ways to do this, depending on your needs. You could use the old-school C way and call fopen/fread/fclose, or you could use the C++ fstream facilities (ifstream/ofstream), or if you're using MFC, use the CFile class, which provides functions to accomplish actual file operations.
All of these are suitable for both text and binary, though none have a specific readline functionality. What you'd most likely do instead in that case is use the fstream classes (fstream.h) and use the stream operators (<< and >>) or the read function to read/write blocks of text:
int nsize = 10;
std::vector<char> somedata(nsize);
ifstream myfile;
myfile.open("<path to file>");
myfile.read(somedata.data(), nsize);
myfile.close();
Note that, if you're using Visual Studio 2005 or higher, traditional fstream may not be available (there's a new Microsoft implementation, which is slightly different, but accomplishes the same thing).
To open and read a text file line per line, you could use the following:
// define your file name
string file_name = "data.txt";
// attach an input stream to the wanted file
ifstream input_stream(file_name);
// check stream status
if (!input_stream) cerr << "Can't open input file!";
// file contents
vector<string> text;
// one line
string line;
// extract all the text from the input file
while (getline(input_stream, line)) {
// store each line in the vector
text.push_back(line);
}
To open and read a binary file you need to explicitly declare the reading format in your input stream to be binary, and read memory that has no explicit interpretation using stream member function read():
// define your file name
string file_name = "binary_data.bin";
// attach an input stream to the wanted file
ifstream input_stream(file_name, ios::binary);
// check stream status
if (!input_stream) cerr << "Can't open input file!";
// use function that explicitly specifies the amount of block memory read
int memory_size = 10;
// allocate 10 bytes of memory on heap
char* dynamic_buffer = new char[memory_size];
// read 10 bytes and store in dynamic_buffer
file_name.read(dynamic_buffer, memory_size);
When doing this you'll need to #include the header : <iostream>
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream file;
file.open ("codebind.txt");
file << "Please writr this text to a file.\n this text is written using C++\n";
file.close();
return 0;
}
#include <iostream>
#include <fstream>
using namespace std;
void main()
{
ifstream in_stream; // fstream command to initiate "in_stream" as a command.
char filename[31]; // variable for "filename".
cout << "Enter file name to open :: "; // asks user for input for "filename".
cin.getline(filename, 30); // this gets the line from input for "filename".
in_stream.open(filename); // this in_stream (fstream) the "filename" to open.
if (in_stream.fail())
{
cout << "Could not open file to read.""\n"; // if the open file fails.
return;
}
//.....the rest of the text goes beneath......
}
Follow the steps,
Include Header files or name space to access File class.
Make File class object Depending on your IDE platform ( i.e,
CFile,QFile,fstream).
Now you can easily find that class methods to open/read/close/getline or else of any file.
CFile/QFile/ifstream m_file;
m_file.Open(path,Other parameter/mood to open file);
For reading file you have to make buffer or string to save data and you can pass that variable in read() method.
**#include<fstream> //to use file
#include<string> //to use getline
using namespace std;
int main(){
ifstream file;
string str;
file.open("path the file" , ios::binary | ios::in);
while(true){
getline(file , str);
if(file.fail())
break;
cout<<str;
}
}**
#include <fstream>
ifstream infile;
infile.open(**file path**);
while(!infile.eof())
{
getline(infile,data);
}
infile.close();
fstream are great but I will go a little deeper and tell you about RAII.
The problem with a classic example is that you are forced to close the file by yourself, meaning that you will have to bend your architecture to this need. RAII makes use of the automatic destructor call in C++ to close the file for you.
Update: seems that std::fstream already implements RAII so the code below is useless. I'll keep it here for posterity and as an example of RAII.
class FileOpener
{
public:
FileOpener(std::fstream& file, const char* fileName): m_file(file)
{
m_file.open(fileName);
}
~FileOpeneer()
{
file.close();
}
private:
std::fstream& m_file;
};
You can now use this class in your code like this:
int nsize = 10;
char *somedata;
ifstream myfile;
FileOpener opener(myfile, "<path to file>");
myfile.read(somedata,nsize);
// myfile is closed automatically when opener destructor is called
Learning how RAII works can save you some headaches and some major memory management bugs.