Using fstream and fstream.eof. Working with files - c++

I'm trying to make a programm, which will read the file, change specified word to symbols '#' and write back to same file. But I have problems with that.
1st question.
It seems like I need to store file in buffer before writing it to the file. How should I do it?
2nd question:
I cant understand why loop in this code never ends? It's about 200 words in that file, but I always get memory exception and i gets 10075.
int main(int argc, char* argv[]){
char** temp = new char*[10000];
int i = 0;
fstream fTemp("D:\doc.txt", ios_base::in);
while (!fTemp.eof()){
temp[i] = new char[50];
fTemp >> temp[i];
temp[i][1] = '#';
cout << temp[i] << endl;
i++;
}
fTemp.open("D:\doc.txt", ios_base::trunc);
for (int i = 0; i < sizeof(*temp); i++){
fTemp << temp[i];
}
_getch();
}

First, you should use getline as your usage of eof is incorrect (eof bit is set only after failed read).
Next, store the strings in a std::vector<string>. This will allow you to not care about memory management (current one is leaking) and provide a more flexible solution.
std::string buffer;
std::vector<string> data;
while(std::getline(fTemp,buffer)) {
data.push_back(buffer);
}
The problem you probably have, is the incorrect eof() call, buy you should check you cout output to determine the problem with this code.

to store the data of file in a buffer, you can get the size of file and use the function read to get all file data. see this code:
// Load file in a buffer
ifstream fl(FileName);
fl.seekg(0, ios::end);
size_t len = fl.tellg();
char* fdata = new char[len];
fl.seekg(0, ios::beg);
fl.read(fdata, len);
fl.close();
in your case the same fstream that you used to open are being used to write without close the file before reopen.
Your loop never ends because it is a pointer, and it size isn't managed, the better way is get the size of file while it is open, in this case the size of file is the "size_t len".
to rewrite your code you can create another stream, see this code:
// Write File
ofstream flOut(FileName, ios_base::trunc);
flOut.write(fdata, len);
flOut.close();
between these two codes above, you can change the data of fdata, but what exactly you wanna make? is replace some word to symbol '#'? which word?

Related

Reading duplicated objects on files C++

I'm having some trouble with creating a file system to my program in C++. Well, I am creating a new student, and, if he is the last object that I'm creating before saving the files and closing the program, it gets duplicated. For example, two objects: Daniel, Paul. It shows just the last one duplicated: Daniel, Paul, Paul - in the file.txt.
Here is some code of mine:
FILE READING:
ifstream file;
file.open("file.txt");
while (1)
{
Student *p = new Student();
if (file.eof() || file.bad() || file.fail())
{
break;
}
getline(file, ALLTHESTRINGVARIABLES);
p->STRINGVARIABLES = ALLTHESTRINGVARIABLES;
file >> ANOTHERVARIABLES;
p->NOTSTRINGVARIABLES = ANOTHERVARIABLES;
students.push_back(p);
}
file.close();
FILE WRITING:
fstream file;
file.open("file.txt", ios::out | ios::trunc);
for(unsigned int i = 0; i < students.size(); i++){
file << students[i]->VARIABLEEXAMPLE << endl;
}
file.close();
Thank you!!
The eof(), bad(), fail() will only return true after a try to read some bytes from the file without success. So, put the if verification after the getline().
And just make the new instance of the Student after this if to avoid a memory leak.
Like that:
while (1)
{
getline(file, ALLTHESTRINGVARIABLES);
if (file.eof() || file.bad() || file.fail())
break;
Student *p = new Student();
p->STRINGVARIABLES = ALLTHESTRINGVARIABLES;
file >> ANOTHERVARIABLES;
p->NOTSTRINGVARIABLES = ANOTHERVARIABLES;
students.push_back(p);
}
eof() will not return true until you've actually tried to read beyond the end of the file which is why you see the last line duplicated. The getline will fail and ALLTHESTRINGVARIABLES will contain the values from the latest successful read. You should instead check if the extraction actually succeeded before storing a new Student.
Since you mix unformatted and formatted input, you should also remove the newline (or whatever character you use to separate the records) from the stream.
Change the loop to:
if (std::ifstream file("file.txt"); file)
{
while (std::getline(file, ALLTHESTRINGVARIABLES) >> ANOTHERVARIABLES)
{
// remove the newline or whatever whitespace char you use as record separator
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Student *p = new Student;
p->STRINGVARIABLES = ALLTHESTRINGVARIABLES;
p->NOTSTRINGVARIABLES = ANOTHERVARIABLES;
students.push_back(p);
}
}
I also suggest that you don't store pointers (unless you use dynamic dispatch) but instead store the actual Student objects in a std::vector<Student>. If dynamic dispatch is used, then store std::unique_ptr<Student> in the vector.

C++ - Read the bytes of any file into an unsigned char array

I have an assignment where I have to implement the Rijndael Algorithm for AES-128 Encryption. I have the algorithm operational, but I do not have proper file input/output.
The assignment requires us to use parameters passed in from the command line. In this case, the parameter will be the file path to the particular file the user wishes to encrypt.
My problem is, I am lost as to how to read in the bytes of a file and store these bytes inside an array for later encryption.
I have tried using ifstream and ofstream to open, read, write, and close the files and it works fine for plaintext files. However, I need the application to take ANY file as input.
When I tried my method of using fstream with a pdf as input, it would crash my program. So, I now need to learn how to take the bytes of a file, store them inside an unsigned char array for Encryption, and then store them inside another file. This process of encryption and storage of ciphertext needs to occur in 16 byte intervals.
The below implementation is my first attempt to read files in binary mode and then write whatever was read in another file also in binary mode.
The output is readable in a hex reader.
int main(int argc, char* argv[])
{
if (argc < 2)
{
cerr << "Use: " << argv[0] << " SOURCE_FILEPATH" << endl << "Ex. \"C\\Users\\Anthony\\Desktop\\test.txt\"\n";
return 1;
}
// Store the Command Line Parameter inside a string
// In this case, a filepath.
string src_fp = argv[1];
string dst_fp = src_fp.substr(0, src_fp.find('.', 0)) + ".enc";
// Open the filepaths in binary mode
ifstream srcF(src_fp, ios::in | ios::binary);
ofstream dstF(dst_fp, ios::out | ios::binary);
// Buffer to handle the input and output.
unsigned char fBuffer[16];
srcF.seekg(0, ios::beg);
while (!srcF.eof())
{
srcF >> fBuffer;
dstF << fBuffer << endl;
}
dstF.close();
srcF.close();
}
The code implementation does not work as intended.
Any direction on how to solve my dilemma would be greatly appreciated.
Like you, I really struggled to find a way to read a binary file into a byte array in C++ that would output the same hex values I see in a hex editor. After much trial and error, this seems to be the fastest way to do so without extra casts.
It would go faster without the counter, but then sometimes you end up with wide chars. To truly get one byte at a time I haven't found a better way.
By default it loads the entire file into memory, but only prints the first 1000 bytes.
string Filename = "BinaryFile.bin";
FILE* pFile;
pFile = fopen(Filename.c_str(), "rb");
fseek(pFile, 0L, SEEK_END);
size_t size = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
uint8_t* ByteArray;
ByteArray = new uint8_t[size];
if (pFile != NULL)
{
int counter = 0;
do {
ByteArray[counter] = fgetc(pFile);
counter++;
} while (counter <= size);
fclose(pFile);
}
for (size_t i = 0; i < 800; i++) {
printf("%02X ", ByteArray[i]);
}

How do I read character by character from a text file and put it in a character array?

I'm trying to read character by character from a text file until EOF, put them into a character array, so that I can manipulate it after. Compiled with g++ without errors, and when run, I'm prompted for the input file but then it just hangs.
int main (int argc, char *argv[]) {
string filename;
ifstream infile;
char *cp, c[1024];
memset (c, 0, sizeof(c));
cp = c;
cout << "Enter file name: " << endl;
cin >> filename;
//open file
infile.open( filename.c_str() );
//if file can't open
if(!infile) {
cerr << "Error: file could not be opened" << endl;
exit(1);
}
while (!infile.eof()); {
infile.get(c, sizeof(infile));
// get character from file and store in array c[]
}
}//end main
You should try the istream::read() method rather than get(). This will help resolve any buffer overruns:
unsigned int chars_read = 0;
//...
// Read in the file.
if (!infile.read(c, sizeof(c))
{
// Handle the read error here.
// Also check for EOF here too.
}
// Obtain the number of characters actually read.
chars_read = infile.gcount();
First off, you don't want to test for eof()! Somehow I start to feel like Don Quixote having found my windmills. However, I do know that you need to check that the input was successful after trying to read it because before attempting to read the stream can't know whether it will be successful.
You program actually doesn't hang! It just waits for you to enter sizeof(infile) characters or end the input (e.g., using Ctrl-D on UNIXes and Ctrl-Z on Windows). Of course, this may look remarkable like a hanging program. You can verify that this is, indeed, the problem by using a smaller size, e.g., 4. Of course, sizeof(infile) is nearly as good as a small random number: It is the size of an object of type std::ifstream and who can tell what that is? You probably meant to use sizeof(c) to make sure that the call to get(c, n) won't write more character than can fit into c.
Try this:
int cont = 0;
while(infile.good()) {
c[cont++] = infile.get();
}

C++ reading text file by blocks

I really didn't find a satisfied answer at google and I/O in C++ is a little bit tricky. I would like to read text file by blocks into a vector if possible. Alas, I couldn't figure out how. I am not even sure, if my infinite loop will be break in all possibilities, because I/O is tricky. So, the best way I was able to figure out is this:
char buffer[1025]; //let's say read by 1024 char block
buffer[1024] = '\0';
std::fstream fin("index.xml");
if (!fin) {
std::cerr << "Unable to open file";
} else {
while (true) {
fin.read(buffer, 1024);
std::cout << buffer;
if (fin.eof())
break;
}
}
Please, note the second line with '\0'. Is it not odd? Can I do something better? Can I read the data into the vector instead of char array? Is it appropriate to read into vector directly?
Thanks for your answers.
PS. Reading by chunks have sense indeed. This code is short but I am storing it in cyclic buffer.
You should be fine doing the following
vector<char> buffer (1024,0); // create vector of 1024 chars with value 0
fin.read(&buffer[0], buffer.size());
The elements in a vector are guaranteed to be stored contiguously, so this should work - but you should ensure that the vector is never empty. I asked a similar question here recently - check the answers to that for specific details from the standard Can I call functions that take an array/pointer argument using a std::vector instead?
std::ifstream fin("index.xml");
std::stringstream buffer;
buffer << fin.rdbuf();
std::string result = buffer.str();
Exactly what you need.
Recently, I have encountered the same problem. I use read and gcount founction to solve it. It works well. Here is the code.
vector<string> ReadFileByBlocks(const char* filename)
{
vector<string> vecstr;
ifstream fin(filename, ios_base::in);
if (fin.is_open())
{
char* buffer = new char[1024];
while (fin.read(buffer, 1024))
{
string s(buffer);
vecstr.push_back(s);
}
// if the bytes of the block are less than 1024,
// use fin.gcount() calculate the number, put the va
// into var s
string s(buffer, fin.gcount());
vecstr.push_back(s);
delete[] buffer;
fin.close();
}
else
{
cerr << "Cannot open file:" << filename << endl;
}
return vecstr;
}

Splitting files in C++

I need to split a file into multiple files without compression. I found this on cpp reference
#include <fstream>
using namespace std;
int main () {
char * buffer;
long size;
ifstream infile ("test.txt",ifstream::binary);
ofstream outfile ("new.txt",ofstream::binary);
// get size of file
infile.seekg(0,ifstream::end);
size=infile.tellg();
infile.seekg(0);
// allocate memory for file content
buffer = new char [size];
// read content of infile
infile.read (buffer,size);
// write to outfile
outfile.write (buffer,size);
// release dynamically-allocated memory
delete[] buffer;
outfile.close();
infile.close();
return 0;
}
and I thought to do it like this. But the problem is ..I can create only the 1st file because I can read data only from the beginning of the file. Can it be done like this and if no..what is the best way to split these files.
The example code doesn't split a file into multiple files; it just
copies the file. To split a file into multiple files, just don't close
the input. In pseudo-code:
open input
decide size of each block
read first block
while block is not empty (read succeeded):
open new output file
write block
close output file
read another block
The important part is not closing the input file, so that each read
picks up exactly where the preceding read ended.
You can seek the stream to the desired position and then read stream. Check this piece of code.
// get size of file
infile.seekg(0,ifstream::end);
size=infile.tellg();
infile.seekg(0);
All you need to do is to remember the position where you stopped reading infile, close outfile, open new outfile, reallocate buffers and read infile to buffer and write to second outfile.
You can read data from anywhere in the file - you already moved to the end and back to the start successfully.
You don't need to though: just write a loop to sequentially read each outputSize and write it to a new file, for some outputSize < size.
Why reinvent the wheel - Try split
Even has the source code for you to get ideas if you want to implement it in C++
I think I have got a solution to your problem...
You read all the first file in a char array.
Then you write the first half of your array in a file, and then second half of you array in other file...
For example :
#include <fstream>
using namespace std;
int main () {
char * buffer;
long size;
ifstream infile ("test.txt",ifstream::binary);
ofstream outfile ("new.txt",ofstream::binary);
ofstream outfile2 ("new2.txt",ofstream::binary);
// get size of file
infile.seekg(0,ifstream::end);
size=infile.tellg();
infile.seekg(0);
// allocate memory for file content
buffer = new char [size];
// read content of infile
infile.read (buffer,size);
// write to outfile
outfile.write (buffer,size/2);
outfile2.write (buffer+size/2,size);
// release dynamically-allocated memory
delete[] buffer;
outfile.close();
infile.close();
outfile2.close();
return 0;
}
You can also read the first half, write it, then read the second half and write it... Just have a look to that :
int main () {
char * buffer;
long size;
long halfSize;
ifstream infile ("test.txt",ifstream::binary);
ofstream outfile ("new.txt",ofstream::binary);
ofstream outfile2 ("new2.txt",ofstream::binary);
// get size of file
infile.seekg(0,ifstream::end);
size=infile.tellg();
infile.seekg(0);
halfSize = static_cast<int>(floor(size/2));
// allocate memory for file content
buffer1 = new char[halfSize];
buffer2 = new char[size-halfSize];
// read content of infile
infile.read (buffer1,halfSize);
infile.read (buffer2,size-halfSize);
// write to outfile
outfile.write (buffer1,halfSize);
outfile2.write (buffer2,size-halfSize);
// release dynamically-allocated memory
delete[] buffer;
delete[] buffer2;
outfile.close();
infile.close();
outfile2.close();
return 0;
}