Reading good only first line of binary file - c++

Functions should create Complex (my structure) vector, than save it to binary file and than read it from binary file. The problem is that it reads good only first line.
The structure is good. Everything besides reading is working well. These are read and write functions:
void saveVectorBin(vector<Complex> &v, const string filename) {
ofstream output;
output.open(filename, ios::binary);
if (output)
{
for (auto i: v) {
output.write(reinterpret_cast<char*> (&i), sizeof(i));
output << endl;
}
cout << "Wektor zapisany do pliku " << filename << endl;
output.close();
}
else cout << endl << "BLAD TWORZENIA PLIKU BIN" << endl;
}
vector<Complex> readComplexVectorBin(const string &filename) {
vector<Complex> v;
ifstream input;
input.open(filename, ifstream::binary);
if (input) {
Complex line;
while (input.read(reinterpret_cast<char*> (&line), sizeof(Complex))) {
v.push_back(Complex(line));
}
input.close();
}
else cout << endl << "BLAD ODCZYTU PLIKU" << endl;
return v;
}
Should show:
26.697 + 7.709i
20.133 + 23.064i
9.749 + 8.77i
Instead it shows:
26.697 + 7.709i
1.43761e-57 + 1.83671e-43i
1.26962e+306 + -2.39343e-259i

Your issue is that you are inserting a newline into a binary file.
output << endl;
adds data to your file that
while (input.read(reinterpret_cast<char*> (&line), sizeof(Complex))) {
v.push_back(Complex(line));
}
fails to take into consideration. You either need to get rid of output << endl; in your writing loop (easiest solution) or read in and discard the newline in your reading loop (hardest solution).

Related

Appending strings to text files in C++

C++ beginner here,
I am trying to append some text to a pre-written .txt file where every line there is a word.
I have been using the method ofstream and ifstream as seen below, but everytime I try to write something, it erases the file. (I am not allowed to use ios:app or simillar)
int append_new_word() {
//First I read everything on the list and save it to a string called Words_in_List
ifstream data_wordlist_in("woerterliste"); //Opens the txt file
if (!data_wordlist_in) // checks if the file exists
{
cout << "File does not exist!" << endl;
return 1;
}
string Word;
int line = 0;
string Vorhandene_Woerter;
std::getline(data_wordlist_in, Wort);
do { //line counter, goes through all lines and save it to a string
line++;
std::getline(data_wordlist_in, Word);
Words_in_List = Words_in_List + "\n" + Word;
} while (!data_wordlist_in.eof());
cout << Words_in_List << endl;
data_wordlist_in.close();
//HEre it should save the string again in the list word per word with the neu appended word
ofstream data_wordlist_out("woerterliste"); //opens ofstream
if (!data_wordlist_out)
{
cout << "File does not exist!" << endl;
return 1;
}
string new_word_in_list;
cout << "\n Insert a Word to append: ";
cin >> new_word_in_list;
data_wordlist_out << Words_in_List << endl << new_word_in_list;
data_wordlist_out.close(); //closes ofstream
}
Everytime I try I open my program it erases the list.
Your code has some minor problems, but nothing that matches your description of it.
It does line based input, which is strange because nothing in the problem description indicates that reading a line at a time is necessary.
It counts lines, again for no obvious reason.
It skips the first line (maybe this is deliberate, but if so you didn't mention that).
The loop termination is incorrect (see link in the comments).
The function is declared as returning an int but no return is made.
Here some code that addresses these problems. It reads characters not lines (using get()) which makes reading the input simpler, but essentially it's the same technique as your code.
void append_new_word()
{
string existing_content;
ifstream in("file.txt");
char ch;
while (in.get(ch))
existing_content += ch;
in.close();
cout << "enter a new word ";
string new_word;
cin >> new_word;
ofstream out("file.txt");
out << existing_content << new_word << '\n';
}

How to skip to next line in an ofstream object in c++

I'm trying to make a hash program that makes hashes for you. I know it's been done before but I'm trying to recreate it. The problem I'm having is that I'm trying to add logs for each hash and output it to a "DataLog.txt" file. So far it's going Great! The only problem is that I'm trying to add a newline before each output to the text file. At the moment it writes it to the text file, then when it repeats to write again it just overlaps the previous writing. This is the code I have for the file outputting so far.
std::ofstream file;
file.open("DataLog (2).txt");
file << input << hash;
file.close();
The entire main function I have is also listed below. It might be a little long so get ready.
int main() {
while (1) {
std::cout << "Welcome to SHA256 Generator! Please enter the string you would like to convert to a hash:" << std::endl;
std::string input;
std::cin >> input;
std::cout << "Hash - " << sha256(input);
auto hash = ConvertToString(sha256(input));
std::ofstream file;
file.open("DataLog (2).txt");
file << input << hash;
file.close();
std::cout << std::endl;
std::cout << std::endl;
std::cout << "Would you like to convert another hash? Please enter either yes or no for your respose." << std::endl;
std::string response;
std::cin >> response;
if (response == "no")
return 0;
while (response != "yes" ) {
std::cout << std::endl;
std::cout << "Sorry I didn't get that. Can you try typing either yes or no again?" << std::endl;
std::string responseRepeat;
std::cin >> responseRepeat;
if (responseRepeat == "yes" || responseRepeat == "no") {
clear();
break;
}
}
clear();
}
return 0;
}
Ah I see, you want to add a line before each line. I think what you are looking for lies in file << input << hash;
So since file is your fstream output, you can treat it like cout. So the solution here would be file << input << hash << endl;
Now also make sure to open file in append mode by file.open(filename, ios::app); if you dont want your text to override.

I'm working on reading and writing to files with c++

Hi guys I'm working on my last assignment of the computer science class. I think I'm doing everything fine but something is wrong. Can you take a look at it and tell what I'm doing wronger here.
here is what I get when I try to submit online on zybooks site:
"Your program produced no output"
Expected:
Ryan Hermle
22.99
Lochness Monster
3.50
Wonder Woman
123456.78
here are instructions from professor:
Constructor:
Takes a string parameter and stores that as fileName. Does not need to do anything else.
append:
Takes a record as a parameter that contains a string and a double
Open an output file stream in append mode using fileName
set its precision to 2 and fixed
Output the name, newline, the money, newline
searchName:
Open an input file stream with fileName
Loop while a getline and a double extraction are successful
if the string parameter is equal to the name read from the getline, then return the double
If the loop finishes without finding anything, return -1 to indicate that name was not found.
getData:
Open an input file stream with fileName
Construct an ostringstream
Set its precision to 2 and fixed
Loop while a getline and a double extraction are successful
ignore the \n left by the >> extraction
write the string, newline, double, newline to the ostringstream
return the string contained by the ostringstream
here is my main:
#include "Database.h"
int main()
{
Database db("data.txt");
db.append(Record{"Ryan Hermle", 22.99});
db.append(Record{"Lochness Monster", 3.50});
db.append(Record{"Wonder Woman", 123456.78});
}
and here is my Database.cpp file:
#include "Database.h"
Database::Database(string file)
{
fileName = file;
}
void Database::append(Record data)
{
ofstream out;
out.open(fileName, ios::app);
out << setprecision(2) << fixed;
cout << data.name << endl;
cout << data.money << endl;
out.close();
}
double Database::searchName(string n)
{
Record s;
ifstream in;
in.open(fileName);
while (getline(in, n) >> s.money)
{
in.ignore();
if (n == s.name)
{
return s.money;
}
}
return -1;
}
string Database::getData()
{
Record s;
ifstream ifs;
ifs.open(fileName);
ostringstream oss;
oss << setprecision(2) << fixed;
while(getline(ifs, s.name) >> s.money)
{
ifs.ignore();
oss << s.name << endl << s.money << endl;
cout << oss.str();
}
return oss.str();
}
Thanks for everyone who replied to my post. I was able figure out the error in my program.
The error was in append Function:
cout << data.name << endl;
cout << data.money << endl;
It should be like this:
out << data.name << endl;
out << data.money << endl;

Example for file input to structure members?

I have the following structure:
struct productInfo
{
int item;
string details;
double cost;
};
I have a file that will input 10 different products that each contain an item, details, and cost. I have tried to input it using inFile.getline but it just doesn't work. Can anyone give me an example of how to do this? I would appreciate it.
Edit
The file contains 10 lines that look like this:
570314,SanDisk Sansa Clip 8 GB MP3 Player Black,55.99
Can you provide an example please.
Edit
Sorry guys, I am new to C++ and I don't really understand the suggestions. This is what I have tried.
void readFile(ifstream & inFile, productInfo products[])
{
inFile.ignore(LINE_LEN,'\n'); // The first line is not needed
for (int index = 0; index < 10; index++)
{
inFile.getline(products[index].item,SIZE,DELIMETER);
inFile.getline(products[index].details,SIZE,DELIMETER);
inFile.getline(products[index].cost,SIZE,DELIMETER);
}
}
This is another approach that uses fstream to read the file and getline() to read each line on the file. The parsing of the line itself was left out on purpose since other posts have already done that.
After each line is read and parsed into a productInfo, the application stores it on a vector, so all products could be accessed in memory.
#include <iostream>
#include <fstream>
#include <vector>
#include <iterator>
#include <string>
using namespace std;
struct productInfo
{
int item;
string details;
double cost;
};
int main()
{
vector<productInfo> product_list;
ifstream InFile("list.txt");
if (!InFile)
{
cerr << "CouldnĀ“t open input file" << endl;
return -1;
}
string line;
while (getline(InFile, line))
{ // from here on, check the post: How to parse complex string with C++ ?
// https://stackoverflow.com/questions/2073054/how-to-parse-complex-string-with-c
// to know how to break the string using comma ',' as a token
cout << line << endl;
// productInfo new_product;
// new_product.item =
// new_product.details =
// new_product.cost =
// product_list.push_back(new_product);
}
// Loop the list printing each item
// for (int i = 0; i < product_list.size(); i++)
// cout << "Item #" << i << " number:" << product_list[i].item <<
// " details:" << product_list[i].details <<
// " cost:" << product_list[i].cost << endl;
}
EDIT: I decided to take a shot at parsing the line and wrote the code below. Some C++ folks might not like the strtok() method of handling things but there it is.
string line;
while (getline(InFile, line))
{
if (line.empty())
break;
//cout << "***** Parsing: " << line << " *****" << endl;
productInfo new_product;
// My favorite parsing method: strtok()
char *tmp = strtok(const_cast<char*>(line.c_str()), ",");
stringstream ss_item(tmp);
ss_item >> new_product.item;
//cout << "item: " << tmp << endl;
//cout << "item: " << new_product.item << endl;
tmp = strtok(NULL, ",");
new_product.details += tmp;
//cout << "details: " << tmp << endl;
//cout << "details: " << new_product.details << endl;
tmp = strtok(NULL, " ");
stringstream ss_cost(tmp);
ss_cost >> new_product.cost;
//cout << "cost: " << tmp << endl;
//cout << "cost: " << new_product.cost << endl;
product_list.push_back(new_product);
}
It depends on what's in the file? If it's text, you can use the redirect operator on a file input stream:
int i;
infile >> i;
If it's binary, you can just read it in to &your_struct.
You have to
0) Create a new instance of productInfo, pinfo;
1) read text (using getline) to the first comma (','), convert this string to an int, and put it into pinfo.item.
2) read text to the next comma and put it into pinfo.details;
3) read text to the endline, convert the string to a double, and put it into pinfo.cost.
Then just keep doing this until you reach the end of the file.
Here is how I would use getline. Note that I use it once to read from the input file, and then again to chop that line at ",".
ostream& operator>>(istream& is, productInfo& pi)
{
string line;
getline(is, line); // fetch one line of input
stringstream sline(line);
string item;
getline(sline, item, ',');
stringstream(item) >> pi.item; // convert string to int
getline(sline, item, ',');
pi.details = item; // string: no conversion necessary
getline(sline, item);
stringstream(item) >> pi.cost; // convert string to double
return is;
}
// usage:
// productInfo pi; ifstream inFile ("inputfile.txt"); inFile >> pi;
N.b.: This program is buggy if the input is
99999,"The Best Knife, Ever!",16.95

C++ ofstream - only 1 string gets written to file, previous string is overwritten, why?

i wrote a command line program that shall clean and reorganize our archived server logs by piping line by line to new target files. Each target file has an according regEx filter item so if the line that is red from the sourcefile gets written to this specific target file if it matches the regEx.
I read the regEx strings and their target file strings from a config file and save these information in vectors to be able to dynamically resize them by one with every new taget/filter pair that is red from the config.
The following piece of code shows how I loop through all my source files and for every single of them I read line by line and for every line that could be red I cycle through all the filters defined in the config and if the regEx match the line I write this line to to ofstream. Each time I do this the ofstream gets close()d and clear()ed before I open the new target file in it.
My problem now is that everything works fine except of my target files only contain 1 single string after program ends. It contains the last string that I wrote to the file.
All the strings that I wrote to the file before seem to be overwritten. I think I'm doing something wrong but I don't see what it ist.
Here's the code extract:
void StringDirector::redirect_all() {
ifstream input; //Input Filestream init
ofstream output; //Output Filestream init
string transfer; //Transfer string init
//regex e;
for (unsigned k = 0; k<StringDirector::v_sources_list.size(); k++) { //loop through all sources in v_sources_list vector
cout << endl << " LOOP through sources! Cycle #" << k << " / string is: " << StringDirector::v_sources_list[k] << endl;
input.close(); //close all open input files
input.clear(); //flush
input.open(StringDirector::v_sources_list[k].c_str()); //open v_sources_list[k] with input Filestream
if (!input) {
std::cout << "\nError, File not found: " << StringDirector::v_sources_list[k] << "\nExiting!"; //Throw error if file cannot be opened
exit(1);
}
cout << endl << " " << StringDirector::v_sources_list[k] << " opened" << endl;
getline(input, transfer); //get a first line from input Filestream and write to transfer string
while (input) { //do that as long as there is input
for (unsigned j = 0; j<StringDirector::v_filters_list.size(); j++) { //loop through all filters in v_filters_list vectord
cout << endl << " LOOP through filters! Cycle #" << j << " / string is: " << StringDirector::v_filters_list[j] << endl;
regex e(StringDirector::v_filters_list[j]);
if (regex_search(transfer, e)) {
reopen(output, StringDirector::v_targets_list[j].c_str());
output << transfer << endl;
cout << endl << " -- MATCH! Writing line to: " << StringDirector::v_targets_list[j] << endl ;
}
}
getline(input, transfer);
if (input )cout << endl << "+ got another line: " << transfer << endl;
else cout << endl << "End Of File!" << endl;
}
}
}
EDIT:
i forgot the reopen function I use
template <typename Stream>
void reopen(Stream& pStream, const char * pFile,
std::ios_base::openmode pMode = ios_base::out)
{
pStream.close();
pStream.clear();
pStream.open(pFile, pMode);
}
Try "append" open mode for your file, I guess it will be ios_base::app (see reopen function, 3rd argument).
std::ios_base::out | std::ios_base::app
You need to turn on append mode in this method by adding std::ofstream::app
input.open(StringDirector::v_sources_list[k].c_str());
should become
input.open(StringDirector::v_sources_list[k].c_str(), std::ofstream::app);
by default the mode is std::ofstream::out which starts at the beginning and overwrites everything else.
Source