Reading data from file adds extra spaces - c++

Im trying to code a program that reads a file then copies all of the data and stores it into another file. The code below does that but it adds extra bytes randomly in the file which makes the file 249KB instead of 243KB. Ive found that if i remove the "\n" it doesn't add any extra bytes but instead it removes bytes and makes it 237KB.
std::wifstream in_file("initfs_Win32", std::ios::binary);
in_file.seekg(0, std::ios::beg);
std::wstring in_data;
if (in_file.good()) {
while (std::getline(in_file, in_data))
str_buf += in_data + L"\n"
std::wofstream out_file("initfs");
out_file << str_buf;
out_file.close();
}
in_file.close();
Here is an image of the old (Right) and new (Left) files side by side:
image

If you want to copy one file into another file don't do it line by line, do it this way instead:
std::ifstream source("initfs_Win32", std::ios::binary);
if (not source.is_open())
{
std::cerr << "Error opening file" << std::endl;
}
std::ofstream destiny("initfs", std::ios::binary);
destiny << original.rdbuf();
destiny.close();

Related

Why is there delay when I write on a file using c++?

I've tried to open a file, write something on it, read from the file and do the same process again but the output isn't what I expect, here's the code:
file.open("ciao.txt", std::ios::out);
file << "ciao";
file.close();
file.open("ciao.txt", std::ios::out | std::ios::in);
std::string str;
std::getline(file, str);
cout << str;
file.seekp(0);
file << "addio";
std::getline(file, str);
cout << str;
The expected oputput is "ciao addio", but it only gives me "ciao". I've tried to run it line after line, but the file is edited as soon as the program stops. Can someone help please? I couldn't find anything online ;-;
The problem is a combination of things.
Here you write ciao to the file, no problem - except it doesn't have a newline (\n).
file << "ciao";
Later, you read a line:
std::getline(file, str);
Had there been a \n in the file, EOF would not have been reached and the fstream would still be in good shape for accepting I/O. Now it's not however.
So, either file.clear() after the getline or add a newline to the first output:
file << "ciao\n";
You also need to file.seekg(0); before the last getline.
file.open("ciao.txt", std::ios::out);
file << "ciao";
file.close();
file.open("ciao.txt", std::ios::out | std::ios::in);
std::string str;
std::getline(file, str);
file.clear(); // add this
cout << str;
file.seekp(0);
file << "addio";
file.seekg(0); // add this
std::getline(file, str);
// I added > and < to make it clear what comes from the file:
cout << '>' << str << "<\n";
Output:
ciao>addio<

C++ - std::fstream read() does not read full file

I would like to create a MIDI interpreter to use in a bigger project, but I'm currently facing a huge problem : It seems that in some cases, my file is not completely read, and so I don't have the whole data I need... For example, I have a file that is around 30 000 bytes long, and the fstream::read() function reads only around 3000 of them...
My code is below, if someone may have an idea...
I haven't found any similar question, but if there are any, please tell me.
std::ifstream file;
file.open("Songs/" + filename + ".mid");
if (!file.is_open())
{
std::cerr << "Failed to open file" << std::endl;
return;
}
std::vector<unsigned char> fileData;
while (file.read((char *)&c, 1))
{
fileData.push_back(c);
}
file.close();
By default, file streams use "in + out" mode to open a filestream for a text file. Try to combine exactly "in" (as you read from the file) and "binary" (as your file is not a plain text), something like this:
std::ifstream file;
file.open("Songs/" + filename + ".mid", std::ios_base::in | std::ios_base::binary);
if (!file.is_open())
{
std::cerr << "Failed to open file" << std::endl;
return;
}
std::vector<unsigned char> fileData;
while (file.read((char *)&c, 1))
{
fileData.push_back(c);
}
file.close();

When writing from the buffer to the file, the file becomes one character larger

I use zlib library to compress data from strings and get compressed data also in strings. I load and unload compressed data using fstream. The problem is that sometimes it happens that when a line is written to a file, it becomes one byte larger and I cannot understand why this happens. I checked a row with compressed data and it has the correct size, and I can get decompressed data from it in program without writing in file. Because in the file it turns out one character more, I can no longer decompress this data. When reading such a line from a file, it is accordingly one character more as shown in a text editor.
There are "Sel" says what string size is 82.
This is example of my function which puts compressed string into file:
std::fstream file(filename, std::ios::out, std::ios::binary);
if (!file.is_open()) {
std::cout << "Unable to open file: " << filename << std::endl;
return;
}
std::stringstream someData;
...puts data in "someData"...
std::string compressedData = Compress_String(someData.str());
std::cout << "Comp string: " << compressedData << std::endl;
std::cout << "Comp size: " << compressedData.size() << std::endl;
file << compressedData;
file.close();
I'm surprised that the following line even compiles.
std::fstream file(filename, std::ios::out, std::ios::binary);
Your compiler must support a non-standard constructor. What you need is
std::fstream file(filename, std::ios::out | std::ios::binary);
// ^^^

Error copying text from one file to another c++ fstream

This is my code
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream file;
file.open("text.txt", std::fstream::in | std::fstream::out |
std::fstream::app);
if(!file.is_open())
{
std::cout << "Could not open file(test.txt)" << std::endl;
} else {
file << "These are words \nThese words are meant to show up in the new file \n" <<
"This is a new Line \nWhen the new fstream is created, all of these lines should be read and it should all copy over";
std::string text;
file >> text;
std::cout << text << std::endl;
file.close();
std::fstream newFile;
newFile.open("text2.txt", std::fstream::in | std::fstream::out |
std::fstream::app);
if(newFile.is_open())
{
newFile << text;
}
}
}
I'm trying to copy the contents of text.txt to text2.txt but for some reason the text string always ends up empty. I've checked the files and text gets populated but text2 is empty. What's going wrong here?
When you append a string to an fstream, the input / output position is set to the end of the file. This means that when you next read from the file, all you will see is an empty string.
You can check what the current input position is by using:
file.tellg()
And set the input / output position to the start by using:
file.seekg(0)
The full reference for std::fstream is here.
You're trying to read from the end of the file. The position is set to the end of the last thing you wrote to the file, so, if you want to read what you wrote, you have to reset it:
file.seekg(0);
This will set the position for the input back to the start of the file. Note however that reading from the file the way you do now will simply get you 1 word (up to the first whitespace). If you want to read it all, perhaps you should look at something like: Read whole ASCII file into C++ std::string.

In c++ seekg seems to include cr chars, but read() drops them

I'm currently trying to read the contents of a file into a char array.
For instance, I have the following text in a char array. 42 bytes:
{
type: "Backup",
name: "BackupJob"
}
This file is created in windows, and I'm using Visual Studio c++, so there is no OS compatibility issues.
However, executing the following code, at the completion of the for loop, I get Index: 39, with no 13 displayed prior to the 10's.
// Create the file stream and open the file for reading
ifstream fs;
fs.open("task.txt", ifstream::in);
int index = 0;
int ch = fs.get();
while (fs.good()) {
cout << ch << endl;
ch = fs.get();
index++;
}
cout << "----------------------------";
cout << "Index: " << index << endl;
return;
However, when attempting to create a char array the length of the file, reading the file size as per below results in the 3 additional CR chars attributing to the total filesize so that length is equal 42, which is adding screwing up the end of the array with dodgy bytes.
// Create the file stream and open the file for reading
ifstream fs;
fs.seekg(0, std::ios::end);
length = fs.tellg();
fs.seekg(0, std::ios::beg);
// Create the buffer to read the file
char* buffer = new char[length];
fs.read(buffer, length);
buffer[length] = '\0';
// Close the stream
fs.close();
Using a hex viewer, I have confirmed that file does indeed contain the CRLF (13 10) bytes in the file.
There seems to be a disparity with getting the end of the file, and what the get() and read() methods actually return.
Could anyone please help with this?
Cheers,
Justin
You should open your file in binary mode. This will stop read dropping CR.
fs.open("task.txt", ifstream::in|ifstream::binary);