Read from binary file > data into class object, missing data - c++

I'm currently making a file that reads ASCII file to read binary file instead. It has to put data into an object named Arragements and Customers. However, something is missing. It does not read the first line of the files.
It is reading everything correctly (it seems), except the fact that it doesn't read the first line of the file at all, and instead it adds 5 zeros at the end when it is supposed to not be anything there. In other words, it is not reading everything. Any big mistakes made? I'm changing the code from reading a ASCII file to read a BINARY file instead. If it make any changes, I've added how the readTicketsFromFile looked like when it was written to read ASCII file blow.
Here's the code when reading from ASCII: https://pastebin.com/WswHzpxM
The file format is (10 lines total):
< nr (2) > < amount tickets(4) > < price(3) > < title(30) >
Here's what I ried to make, "translating" the code to read same file in BINARY (It is obviously converted to BINARY file):
#include <fstream> // ifstream, ofstream
#include <iostream> // cout
#include <cstring> // strcpy
#include <cstdlib> // (s)rand
using namespace std;
const int ARRLEN = 35;
// CLASSES
class Arrangement {
private:
char title[ARRLEN]; // Arrangement title/name
int price; // Price pr. ticket
int amountSpaces; // Amounts of spaces/tickets left
int amountSold; // Amounts of tickets sold so far
int totalTicketsOrdered; // Total amount of tickets
int totalCustomersOrdered; // Amount of customers wanting a ticket
public:
Arrangement();
void update(char titt[], int ant, int pri);
void updateAmountWishedTickets(int antBill);
void updateAmountSold(int ant);
bool needPull();
int amountLeft();
int amountOrdered();
void write()
{
cout
<< '\n' << price << "\t"
<< amountSpaces << "\t"
<< amountSold << "\t"
<< totalTicketsOrdered
<< "\t" << totalCustomersOrdered
<< '\t' << title;
}
};
// READ FROM FILE 1
void readTicketsFromFile() {
char title[ARRLEN];
int nr, amount, price; // Variables 3 first "spaces" of the file
int size = 0;
// post/linje på filen.
ifstream infile;
infile.open("tickets.res", ios::in | ios::binary);
if (infile.is_open()) {
infile.seekg(0, ios::end);
size = (int)infile.tellg() / sizeof(Arrangement);
cout << "\n# in file: " << size << endl; // Prints out: 10
// Read from file, supposed to read everything from the file
for (int i = 1; i <= size; i++) {
infile.seekg(i * sizeof(Arrangement));
infile.read((char *)& arrangementer[i], sizeof(Arrangement));
cout << '\n' << i << " read: \n";
arrangementer[i].write(); // Used to see what what's inside the object, 1. missing.
}
}
else cout << "Couldn't open the file";
infile.close();
}
int main() {
readTicketsFromFile();
return 0;
}
What it shoud look like:
https://i.gyazo.com/69c5560766c33ebc15cac25e13b4de72.png
What it looks like:
https://i.gyazo.com/a9081f65ff629f3b57cb2c20750087b5.png

Related

Writing and reading from the same file

This program takes in an input, write it on a file character by character, count the amount of characters entered, then at the end copy it to an array of characters. The program works just fine until we get to the following snippet file.getline(arr, inputLength);. It changes the .txt file data and returns only the first character of the original input.
Any ideas?
#include <iostream>
#include <fstream>
using namespace std;
int getLine(char *& arr);
int main() {
char * arr = NULL;
cout << "Write something: ";
getLine(arr);
return 0;
}
int getLine(char *& arr) {
fstream file("temp.txt");
char input = '\0'; //initialize
int inputLength = 0; //initialize
if (file.is_open()) {
while (input != '\n') { //while the end of this line is not reached
input = cin.get(); //get each single character
file << input; //write it on a .txt file
inputLength++; //count the number of characters entered
}
arr = new char[inputLength]; //dynamically allocate memory for this array
file.getline(arr, inputLength); //HERE IS THE PROBLEM!!! ***
cout << "Count : " << inputLength << endl; //test counter
cout << "Array : " << arr << endl; //test line copy
file.close();
return 1;
}
return 0;
}
I see at least two problems with this code.
1) std::fstream constructor, by default, will open an existing file. It will not create a new one. If temp.txt does not exist, is_open() will fail. This code should pass the appropriate value for the second parameter to std::fstreams constructor that specifies that either a new file needs to be created, or the existing file is created.
Related to this: if the file already exists, running this code will not truncate it, so the contents of the file from this program's previous run will have obvious unexpected results.
2) The intent of this code appears to be to read back in the contents temp.txt that were previously written to it. To do that correctly, after writing and before reading it is necessary to seek back to the beginning of the file. This part appears to be missing.
There is no need in dynamic allocation because the std library functions get confused with mixed arguments such as cstring and pointer to cstring.I tested this code in Visual Studio 2015 compiler. It works good. Make sure to include all of the needed libraries:
#include <iostream>
#include <fstream>
#include<cstring>
#include<string>
using namespace std;
void getLine();
int main() {
cout << "Write something: ";
// no need to pass a pointer to a cstring
getLine();
system("pause");
return 0;
}
void getLine() {
char input[100]; // this is a cstring with
//a safe const number of elements
int inputLength; //to extract length of the actual input
//this function requires cstring as a first argument
// and constant length as a second
cin.get(input, 100, '\n'); //get each single character
//cast streamsize into int
inputLength = static_cast<int>(cin.gcount());
//testing input
cout << "Input: \n";
for (int i = 0; i < inputLength; i++)
{
cout << input[i];
}
cout << endl;
char arr[100];
strcpy_s(arr, input);
cout << "Count : " << inputLength << endl; //test counter
cout << "Array : " << endl; //test line copy
for (int i = 0; i < inputLength; i++)
{
cout << arr[i];
}
cout << endl;
// write cstring to a file
ofstream file;
file.open("temp.txt", ios::out);
if (file.is_open())
{
//write only what was entered in input
for (int i = 0; i < inputLength; i++)
file << arr[i];
file.close();
}
else cout << "Unable to open file";
}

Looping over all files in a folder to proceed script

I attached a simplified C++ code which read a data from a file and get average over the vector and save the output into csv. file. My problem is I have 100 files which named test1.csv, test2.csv,... test100.csv and do the same job for 100 files recursively and want to save the each output as result1.cvs, result2.csv, ... result100.csv respectively.
Frankly, I am a frequent use for Matlab/R and with that this loop is easy to implement but as a beginner for C++, I am puzzling from the beginning.
Each file has one vector of different historical stock price data with same length stock prices (like apple, microsoft, IBM, GM....).
Following is simplified code for your reference but actual code is very complicated one which will generate 25000*30000 matrix output,each.
Sample data in the data file is like;
45.78
67.90
87.12
34.89
34.60
29.98
......
Thanks you for your help in advance.
#include <fstream>
#include <iostream>
int main() {
//std::ifstream infile ("E:\\DATA\\test1.txt");
std::ifstream infile ("E:\\DATA\\test1.csv");
float num;
float total = 0.0f;
unsigned int count = 0;
// While infile successfully extracted numbers from the stream
while(infile >> num) {
total += num;
++count;
}
// don't need the file anymore, close it
infile.close();
// test to see if anything was read (prevent divide by 0)
if (!count) {
std::cerr << "Couldn't read any numbers!" << std::endl;
return 1;
}
// give the average
std::cout << "The average was: " << total/count << std::endl;
std::cout << "The sum was: " << total << std::endl;
std::cout << "The length was: " << count << std::endl;
// pause the console
// std::cin.sync();
//std::cin.get();
std::ofstream myfile;
myfile.open ("E:\\DATA\\result1.csv"); //check!!!!
myfile<<total/count<<","; //Add "," for csc format
myfile.close();
std::cout << "average was sucessfully saved !!!! /n";
return 0;
}
//source http://www.cplusplus.com/forum/general/124221/
It sounds like it would be easiest to run this code in a for loop, updating the filename strings with each iteration. For example:
#include <string>
#include <iostream>
#include <fstream>
int main() {
for (int i = 1; i <= 100; i++) {
std::string inFile;
std::string outFile;
// Add the prefix to the filename
inFile.append("test");
outFile.append("result");
// Add the number to the filename
inFile.append(std::to_string(i));
outFile.append(std::to_string(i));
// Add the suffix to the filename
inFile.append(".csv");
outFile.append(".csv");
// std::cout << inFile << std::endl;
// std::cout << outFile << std::endl;
std::ifstream fin;
std::ofstream fout;
fin.open(inFile);
fout.open(outFile);
// TODO:Use fin and fout
}
return 0;
}
You could also do this with character arrays (C-Strings) if you're more comfortable with that, or if you only have an older version of C++, but the concept is the same. Create a string that concatenates the file prefix, the file number, and the file suffix, and open that instead of hard-coding the filename.

C++ Getting values from file into array

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <fstream>
using namespace std;
void make_array(ifstream& num, int (&array)[50]);
int main()
{
ifstream file; // variable controlling the file
char filename[100]; /// to handle calling the file name;
int array[50];
cout << "Please enter the name of the file you wish to process:";
cin >> filename;
cout << "\n";
file.open(filename);
if (file.fail()) {
cout << "The file failed to open.\n";
exit(1);
} else {
cout << "File Opened Successfully.\n";
}
make_array(file, array);
file.close();
return (0);
}
void make_array(ifstream& num, int (&array)[50])
{
int i = 0; // counter variable
while (!num.eof() && i < 50) {
num >> array[i];
i = i + 1;
}
for (i; i >= 0; i--) {
cout << array[i] << "\n";
}
}
I am trying to read values from a file to an array using fstream. When I try to display the contents of the array, I get 2 really big negative numbers, and then the contents of the file.
Any ideas what I did wrong?
Your use of num.get(array[i]) doesn't match any of its signatures. See get method description. What you want is this:
array[i] = num.get();
As discussed in the comments, you try to read an integer which is encoded as text. For this, you need to use operator>> (which reads any type encoded as string) instead of get (which reads a single byte):
num >> array[i];

Is it possible to use an outputfile as an inputfile later on in code (C++ I/O files)

So what I did was this;
ifstream infile("warehouse.txt"); ffile("updated.txt");
ofstream outfile("updated.txt");
basically what I want to do is read from the inputfile 'warehouse.txt' and store contents in an array and then add this array and an extra array to outputfile 'updated.txt'.
Then I want to use 'updated.txt' as an input file as shown in the code above is this allowed, I basically want to store all the data on updated.txt into one big array i.e combine the two arrays, is this allowed? I tried it and my compiler seemed to screw up and I was reading about using vectors instead but am struggling to understand them. thanks.
here is my overall code what I wanted to do was basically take from an input file the 'fruitname' and its corresponding quantity from an input file. store extra entries in an extraarray and then put both these arrays in an output file as stated above and then use that output as an input file so I can aggreagte the data.
THE PROBLEM:
When I try to store from the updated.txt to array my cout's show that I get random numbers in place of what should be the fruitname and its number.
#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
typedef struct items {
string name;
int quantity;
} items_t;
void fileopenchecker (ifstream &FILE);
int readfromfile (ifstream &FILE, items_t fruit[]);
int extrarray (items_t fruit[]);
void writetooutputfile (ofstream &OFILE, items_t fruit[], int size);
void combinearrays (ifstream &final, items_t overallfruit[], int total);
int main()
{
const int MAX_SIZE = 150;
int Nfruit = 0;
int Nextrafruit = 0;
int total;
std::ifstream infile("warehouse.txt");
std::ofstream outfile("updated.txt");
std::ifstream ffile("updated.txt");
items_t extrafruit[MAX_SIZE], fruit[MAX_SIZE], overallfruit[MAX_SIZE];
fileopenchecker(infile);
Nextrafruit = extrarray(extrafruit);
Nfruit = readfromfile(infile, fruit);
total = Nextrafruit + Nfruit;
infile.close();
writetooutputfile(outfile, fruit, Nfruit);
writetooutputfile(outfile, extrafruit, Nextrafruit);
combinearrays (ffile, overallfruit, total);
ffile.close();
return 0;
}
void combinearrays (ifstream &final, items_t overallfruit[], int total){
int i;
for(i=0; i<total; i++){
final >> overallfruit[i].name >> overallfruit[i].quantity;
cout << overallfruit[i].name << overallfruit[i].quantity << endl;
}
}
void fileopenchecker (ifstream &FILE){
if(!FILE.is_open()){
cout << "Your file was NOT detected!" << endl;
exit(1);
}
else{
cout << "Your file was detected" << endl;
}
}
int readfromfile (ifstream &FILE, items_t fruit[]){
int entries = 0;
while(!FILE.eof()){
FILE >> fruit[entries].name >> fruit[entries].quantity;
cout << fruit[entries].name << fruit[entries].quantity << endl;
entries++;
}
return entries;
}
int extrarray (items_t fruit[]){
int runner=1, exentries =0;
while(runner==1){
cout << "Would you like to add entries to your file? (YES-->1 NO-->0)" << endl;
cin >> runner;
if(runner==0){
break;
}
//take the itemname and quantity and stores it in the array.
cout << "Enter the name of the fruit and its quantity" << endl;
cin >> fruit[exentries].name >> fruit[exentries].quantity;
//debugging:
cout << fruit[exentries].name << fruit[exentries].quantity << endl;
exentries++;
}
return exentries;
}
void writetooutputfile (ofstream &OFILE, items_t fruit[], int size){
int entries = 0;
while(entries < size){
cout << fruit[entries].name << fruit[entries].quantity << endl;
OFILE << fruit[entries].name << fruit[entries].quantity << endl;
entries++;
}
}
"I want to do is read from the inputfile 'warehouse.txt'"
{
std::ifstream ifs("warehouse.txt");
// reading from ifs ...
... "to outputfile 'updated.txt'"
std::ofstream ofs("updated.txt");
// writing to ofs ...
}
... "Then I want to use 'updated.txt' as an input file" ~> create another instance of ifstream:
{
std::ifstream ifs2("updated.txt");
// reading from ifs2 ...
}
Yes, and it's possible to to use just two file streams if you use std::fstream. For example:
#include <fstream>
#include <iostream>
#include <string>
int main(void)
{
std::ifstream infile("a.txt");
// create file for both reading and writing
std::fstream ffile("b.txt", std::fstream::in | std::fstream::out | std::fstream::trunc);
// read contents of file a and write to file b
std::string line;
while (std::getline(infile, line))
{
std::cout << line << std::endl;
ffile << line << std::endl;
}
// flush the output to disk
ffile.flush();
// go back to the start of the output file before reading from it
ffile.seekg(0);
// read contents of output file again.
while (std::getline(ffile, line))
{
std::cout << line << std::endl;
}
return 0;
}

Split a Large File In C++

I'm trying to write a program that takes a large file (of any type) and splits it into many smaller "chunks". I think I have the basic idea down, but for some reason I cannot create a chunk size over 12 kb. I know there are a few solutions on google, etc. but I am more interested in learning what the origin of this limitation is then actually using the program to split files.
//This file splits are larger into smaller files of a user inputted size.
#include<iostream>
#include<fstream>
#include<string>
#include<sstream>
#include <direct.h>
#include <stdlib.h>
using namespace std;
void GetCurrentPath(char* buffer)
{
_getcwd(buffer, _MAX_PATH);
}
int main()
{
// use the function to get the path
char CurrentPath[_MAX_PATH];
GetCurrentPath(CurrentPath);//Get the current directory (used for displaying output)
fstream bigFile;
string filename;
int partsize;
cout << "Enter a file name: ";
cin >> filename; //Recieve target file
cout << "Enter the number of bites in each smaller file: ";
cin >> partsize; //Recieve volume size
bigFile.open(filename.c_str(),ios::in | ios::binary);
bigFile.seekg(0, ios::end); // position get-ptr 0 bytes from end
int size = bigFile.tellg(); // get-ptr position is now same as file size
bigFile.seekg(0, ios::beg); // position get-ptr 0 bytes from beginning
for (int i = 0; i <= (size / partsize); i++)
{
//Build File Name
string partname = filename; //The original filename
string charnum; //archive number
stringstream out; //stringstream object out, used to build the archive name
out << "." << i;
charnum = out.str();
partname.append(charnum); //put the part name together
//Write new file part
fstream filePart;
filePart.open(partname.c_str(),ios::out | ios::binary); //Open new file with the name built above
//Check if near the end of file
if (bigFile.tellg() < (size - (size%partsize)))
{
filePart.write(reinterpret_cast<char *>(&bigFile),partsize); //Write the selected amount to the file
filePart.close(); //close file
bigFile.seekg(partsize, ios::cur); //move pointer to next position to be written
}
//Changes the size of the last volume because it is the end of the file
else
{
filePart.write(reinterpret_cast<char *>(&bigFile),(size%partsize)); //Write the selected amount to the file
filePart.close(); //close file
}
cout << "File " << CurrentPath << partname << " produced" << endl; //display the progress of the split
}
bigFile.close();
cout << "Split Complete." << endl;
return 0;
}
Any ideas?
You are writing to the split file, but not reading from the bigfile. What you are writing it the in-memory structure of the bigfile, not the contents of bigfile. You need to allocate a buffer, read into it from bigfile and write it to the splitfile(s).