My file is not being copied correctly - c++

I am new to c++ and kind of learned on my own, so I have a program that is supposed to read in the specified file from a file path and in theory make an exact copy. My issue is that I am always off (as in off by bytes, Ex, a 173 kb file is 177kb), and from what I am seeing the bigger the file the more I'm off. So why I am I wrong and is there a better way to do it?
int main()
{
//I was monitering memory usage, some reason if i wrote to console to fast, I couldn't moniter memory
system("pause");
ifstream inputFile;
inputFile.open("C:\\Users\\Tallennar\\Documents\\Tables.docx", ios::in | ios::binary);
ofstream outputFile;
outputFile.open("word.docx", ios::binary);
char buffer[257] = { ' ' };//one extra for \0
if (!inputFile)
printf("failed to open input file");
if (!outputFile)
printf("failed to open outputfile \n");
//gets my file size
inputFile.seekg(0, ios::end);
size_t fileSize = inputFile.tellg();
inputFile.seekg(0, ios::beg);
//some math to see how many times I need to loop
int leftOverFromIterations = fileSize % 256;
int fileSizeIterations = (fileSize - leftOverFromIterations) / 256;
int bufferSize = sizeof(buffer);
//loops through to print to output file
for (int i = 0; i <= fileSizeIterations; i++)
{
inputFile.read(buffer, bufferSize);
//so i dont get funny chars
buffer[256] = '\0';
outputFile.write(buffer, bufferSize);
//for me to see what is getting printed
std::cout << buffer;
}
//since not every file is divisible by 256, get the
// leftovers from the above for loop
inputFile.read(buffer, leftOverFromIterations);
//close files
inputFile.close();
outputFile.close();
system("pause");
return 0;
}

Several problems:
The for loop is running too many times, it should use i < fileSizeIterations.
You're overwriting the last character of the buffer with \0. You should set bufferSize to 1 less than the size of the array, so you don't read into the character needed for the null. Or you should use std::string instead of a C-style string.
You're not copying the leftovers to the output file.
You should also avoid hard-coding 256 throughout the code, and use bufferSize there.
int main()
{
//I was monitering memory usage, some reason if i wrote to console to fast, I couldn't moniter memory
system("pause");
ifstream inputFile;
inputFile.open("C:\\Users\\Tallennar\\Documents\\Tables.docx", ios::in | ios::binary);
ofstream outputFile;
outputFile.open("word.docx", ios::binary);
char buffer[257] = { ' ' };//one extra for \0
if (!inputFile)
printf("failed to open input file");
if (!outputFile)
printf("failed to open outputfile \n");
//gets my file size
inputFile.seekg(0, ios::end);
size_t fileSize = inputFile.tellg();
inputFile.seekg(0, ios::beg);
int bufferSize = sizeof(buffer)-1;
//some math to see how many times I need to loop
int leftOverFromIterations = fileSize % bufferSize;
int fileSizeIterations = (fileSize - leftOverFromIterations) / bufferSize;
//loops through to print to output file
for (int i = 0; i < fileSizeIterations; i++)
{
inputFile.read(buffer, bufferSize);
//so i dont get funny chars
buffer[bufferSize] = '\0';
outputFile.write(buffer, bufferSize);
//for me to see what is getting printed
std::cout << buffer;
}
//since not every file is divisible by bufferSize, get the
// leftovers from the above for loop
inputFile.read(buffer, leftOverFromIterations);
//so i dont get funny chars
buffer[leftOverFromIterations] = '\0';
outputFile.write(buffer, leftOverFromIterations);
//for me to see what is getting printed
std::cout << buffer;
//close files
inputFile.close();
outputFile.close();
system("pause");
return 0;
}

Why not use getline() instead? A lot less confusing.
int main()
{
//I was monitering memory usage, some reason if i wrote to console to fast, I couldn't moniter memory
system("pause");
ifstream inputFile;
inputFile.open("C:\\Users\\Tallennar\\Documents\\Tables.docx", ios::in | ios::binary);
ofstream outputFile;
outputFile.open("word.docx", ios::binary);
if (!inputFile)
{
printf("failed to open input file");
return 0; //if you didn't open the file don't continue
}
if (!outputFile)
{
printf("failed to open outputfile \n");
return 0; //if you didn't open the file don't continue
}
string line;
while(getline(inputFile, line ))
{
outputFile << line;
}
inputFile.close();
outputFile.close();
system("pause");
return 0;
}
Note: I added return 0; to your if statements so it stops if it can't open the files.
Disclaimer: I have not run this code as I do not have a compiler that can deal with files off hand.

Related

Read big files in C++ but also small files as well in C++?

I want to make a C++ program to read huge files (like 50Gb each) while you have only 4 or 8Gb of RAM.
I want this algorithm to be faster and work with small files as well.
This is the code I have until now:
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
//Making a buffer to store the chuncks of the file read:
// Buffer size 1 Megabyte (or any number you like)
size_t buffer_size = 1<<20;
char *buffer = new char[buffer_size];
int main(){
string filename="stats.txt";
//compute file size
size_t iFileSize = 0;
std::ifstream ifstr(filename.c_str(), std::ios::binary); // create the file stream - this is scoped for destruction
if(!ifstr.good()){
cout<<"File is not valid!"<<endl;
exit(EXIT_FAILURE);
}
//get the file size
iFileSize = ifstr.tellg();
ifstr.seekg( 0, std::ios::end ); // open file at the end to get the size
iFileSize = (int) ifstr.tellg() - iFileSize;
cout<<"File size is: "<<iFileSize<<endl;
//close the file and reopen it for reading:
ifstr.close();
cout<<"Buffer size before check is:"<<buffer_size<<endl;
if(buffer_size>iFileSize){
buffer_size=iFileSize;
}
cout<<"Buffer size after check is:"<<buffer_size<<endl;
ifstream myFile;
myFile.open(filename);
if(myFile.fail()){
cerr<<"Error opening file!"<<endl;
exit(EXIT_FAILURE);
}
if(!myFile.good()){
cout<<"File is not valid!"<<endl;
exit(EXIT_FAILURE);
}
if(!myFile.is_open()){
cout<<"File is NOT opened anymore!"<<endl;
return 1;
}
while(myFile.is_open()&&myFile){
// Try to read next chunk of data
myFile.read(buffer, buffer_size);
// Get the number of bytes actually read
size_t count = myFile.gcount();
// If nothing has been read, break
if (!count){
break;
}
// Do whatever you need with first count bytes in the buffer:
string line;
while(getline(myFile, line)){
if(!line.empty()){
cout <<"Line: '" << line << "'" <<endl;
}
}
}
delete[] buffer;
buffer = NULL;
myFile.close();
return 0;
}
My files could have blank lines between the text line, also even the first lines could be blank lines.
So, I tested the program on a small file size (128kb in size) named to see how it works. But it doesn't work. It doesn't display any line on the screen even the file is so small.
What is wrong? Also, if I change the buffer size to a very small number, it reads just first one or two lines but why it doesn't loop to the end of the file to read and display all of the lines from that small file? Any help, please?
Thank you in advance!
This is the test file: (It starts with a few blank lines also.)
Population UK: 97876876723
Population France: 898989
This is the test end of the file: Yay!
This is the result:
And no line from file is displayed.

Why am I getting a conversion function error?

I have to read in an external file called text.txt. The file could contain a lot of data (and def > 83 chars) and I want to ignore the spaces. Then I need to get the total amount of chars in the file (not incl. spaces). I have to use strlen. I am getting a conversion type error which is confusing because I thought strlen returns an int. The error is on strlen(inputString) and more specifically on (inputString).
int main() {
fstream inFile;
string inputString;
inFile.open("text.txt", ios::in);
if (inFile) {
getline(inFile, inputString, ' ');
while (inFile)
{
int tempStringLength = strlen(inputString);
int total = 0;
total += tempStringLength;
}
}
else
cerr << "Unable to open file text.txt";
exit(1);
return 0;
}
I expect the total to be the total # of chars in the file.
The strlen function returns a size_t result which is usually equivalent to unsigned int on your platform.
Also, I haven't tried your code but it reads like an infinite loop. You might want to rearrange it like the following:
int main() {
fstream inFile;
string inputString;
inFile.open("text.txt", ios::in);
unsigned int total = 0;
if (inFile) {
while (inFile)
{
getline(inFile, inputString, ' ');
unsigned int tempStringLength =inputString.length();
total += tempStringLength;
//Or maybe combine the two previous statements into:
//total += inputString.length();
}
}
else
cerr << "Unable to open file text.txt";
exit(1);
return 0;
}
P.S.: Also, strlen expects a char[] as input. I've changed that to be string.length() instead.

Implementing Huffman Tree

I have a program that produces a huffman tree based on ascii character frequency read in a text input file. The huffman codes are stored in a string array of 256 elements, empty string if character is not read.
I am now trying to implement the huffman tree by writing a function that takes my huffman codes that are stored in a string array and outputting the encoding of input file into an output file.
I soon realized that my current approach defeats the meaning of the assignment. I have tried simply copying the string of codes to output file making my encoded output file bigger than the input file.
I am hoping to get help in changing my current function so that it can output the bits into output file making the output file smaller than input file. I am stuck because I am only reading and writing bytes currently?
My current function(fileName being input file parameter, fileName2 being output file parameter):
void encodeOutput(const string & fileName, const string & fileName2, string code[256]) {
ifstream ifile;//to read file
ifile.open(fileName, ios::binary);
if (!ifile)//to check if file is open or not
{
die("Can't read again"); // function that exits program if can't open
}
ofstream ofile;
ofile.open(fileName2, ios::binary);
if (!ofile) {
die("Can't open encoding output file");
}
int read;
read = ifile.get();//read one char from file and store it in int
while (read != -1) {//run this loop until reached to end of file(-1)
ofile << code[read]; //put huffman code of character into output file
read = ifile.get();//read next character
}
ifile.close();
ofile.close();
}
You can't just use ofile << code[read]; if what you need is writing bits, the smallest unit ofstream understands is a byte.
To overcome that, you can write your bits to some sort of "bit buffer" (a char will do) and write that out once it has 8 bits. I don't know exctly what you code strings look like, but this should do:
char buffer = 0, bit_count = 0;
while (read != -1) {
for (int b = 0; b < code[read].size(); b++) {
buffer << 1;
buffer |= code[read][b] != 0;
bit_count++;
if (bit_count == 8) {
ofile << buffer;
buffer = 0;
bit_count = 0;
}
}
read = ifile.get();
}
if (bit_count != 0)
ofile << (buffer << (8 - bit_count));

Reading any file as binary in C++?

How might I read any file type as binary in C++? So far, I've been able to read .txt files in binary using std::bitset like so:
std::ifstream myfile;
myfile.open("example.txt", std::ios::binary);
while (getline (myfile, line) ) {
for (std::size_t i = 0; i<line.size(); ++i) {
std::bitset<8> a = std::bitset<8>(line[i]); //convert every character to binary, save it in a
std::cout<<((char)std::bitset<8>(a).to_ulong())<<'\n';
}
}
In the first line, how might I read a file like sound.mp3 or word.docx as a binary file? I understand that in they really just are binary files, but how can I read them as such?
Thanks!
By casting from a block of memory of chars to binary, you can read a file as binary.
std::streampos size;
char * memblock;
std::ifstream myfile ("sound.mp3", std::ios::in|std::ios::binary|std::ios::ate);
//ios::ate puts the reader at the end of the file
if (file.is_open())
{
size = myfile.tellg();
memblockChar = new char [size];
myfile.seekg (0, std::ios::beg);
myfile.read (memblockChar, size);
myfile.close();
for (int i = 0; i<size; i++) {
std::cout << (((std::bitset<8>)memblockChar[i]).to_ulong()) << '\n';
}
delete[] memblockChar;
}
else std::cout<<"Unable to open file"<<std::endl;
This could be used in a main method, or anywhere else.

How to make the 'read' function start from the beginning of the file?

I am trying to read a binary file and I am using the f_in.read((char(*) &tmp, sizeof(tmp)) function. However, each time I call this function it continues reading the file from the position where the previous read function had left off. Is it possible to make the read function start from the beginning of the file each time it is called?
Opening the pixmap.bin file:
int main(){
ifstream f_in;
f_in.open("Pixmap.bin", ios::binary);
if (f_in.fail()) {
cerr<<"Error while opening the file pixmap.bin"<<endl;
f_in.close();
exit(EXIT_FAILURE);
}
The function that I want to use with read starting from the beginning each time:
void Read_Dimensions(ifstream &f_in, int Dimensions[2]) {
uint tmp(0);
for(int i=0; i<2;i++) {
f_in.read((char*) &tmp, sizeof(tmp));
Dimensions[i]=tmp;
}
}
this is relative to the file pointer, try reading this page in the section 'File pointer':
http://www.eecs.umich.edu/courses/eecs380/HANDOUTS/cppBinaryFileIO-2.html
Here the example the give:
int main()
{
int x;
streampos pos;
ifstream infile;
infile.open("silly.dat", ios::binary | ios::in);
infile.seekp(243, ios::beg); // move 243 bytes into the file
infile.read(&x, sizeof(x));
pos = infile.tellg();
cout << "The file pointer is now at location " << pos << endl;
infile.seekp(0,ios::end); // seek to the end of the file
infile.seekp(-10, ios::cur); // back up 10 bytes
infile.close();
}
Wish that helps you.