I'm working on a project where I need to read a binary file and then operate on the data(count how many times 3 appears). My approach was to use read() to store data into a char buffer. Then operate on the buffer. My biggest issue is using read() correctly, I don't believe it is storing any data into char buffer. char buffer remains empty after read() is called.
// Program reads how many times the integer 3 occurs in a binary file
#include <iostream>
#include <fstream> // needed to use files
using namespace std;
int main()
{
int count = 0;
char buffer[32];
int size = sizeof(buffer) / sizeof(buffer[0]);
// open file "example.bin"
fstream file("example.bin", ios::in | ios::ate | ios::binary);
if(!file)
{
cout << "Error opening file" << endl;
return 0;
}
cout << "opened file" << endl;
// reading the data into memory
file.read(reinterpret_cast<char *>(buffer), sizeof(buffer));
for(int i = 0; i < size; i++)
{
if (buffer[i] == '3')
count++;
}
cout << "There exists " << count << " threes in this file." << endl;
// close file
file.close();
return 0;
}
Related
I am reading data from a comma delimited csv file. I would like to verify that the file has data before reading and return an error if the file doesn't have any data.
const char* sample_data_file = "sample_data1.csv" ;
std::ifstream file(sample_data_file);
Thanks!
A simple call to stat will tell you if the file is empty. That should be enough to solve your problem.
check the size of the file when you open it?
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
ifstream myfile ("C:/temp/sample1.csv");
// this gives you the number of bytes in the file.
if (myfile.is_open())
{
long begin, end;
begin = myfile.tellg();
myfile.seekg (0, ios::end);
end = myfile.tellg();
if(end-begin == 0)
{
cout << "file is empty \n";
}
else
{
cout << "size: " << (end-begin) << " bytes." << endl;
}
myfile.close();
}
else cout << "Unable to open file \n";
return 0;
}
Why my following code fails to read single integer from file?
It displays "fail() reading" followed by "0".
On linux ubuntu gcc compiler.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream fout2("int_data",ios::binary|ios::out);
int a = 2;
fout2.write((char*)&a,sizeof(a));
int b=0;
ifstream fin2("int_data",ios::binary|ios::in);
fin2.read((char*)&b,sizeof(b));
if(fin2.fail())
cout << "fail() reading" << endl;
cout << b << endl;
}
This could fail for a couple reasons:
Your OS may be protecting you from opening a file that is currently opened for writing
You may not have flushed your data to the file
You can solve both of these by using close before you construct fin2:
ofstream fout2("int_data", ios::binary);
const int a = 2;
fout2.write(reinterpret_cast<const char*>(&a), sizeof(a));
fout2.close();
int b = 0;
ifstream fin2("int_data", ios::binary);
if(!fin2.read(reinterpret_cast<char*>(&b), sizeof(b))) {
cout << "fail() reading" << endl;
}
cout << b << endl;;
Live Example
I have tried two different while loops. I think they have a similar problem. Neither of them terminate or give any output.
The task is to copy (byte for byte) one file into another. The file does not have to have endlines, nor does it have to be a .txt file (it could be .exe...).
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
char c, c1, c2;
ifstream inFile;
ofstream outFile;
inFile.open("blackbird.txt");
if (inFile.fail())
{
cout << "\nThe file was not successfully opened for reading."
<< "\nPlease check that the file currently exists.\n\n";
exit(1);
}
cout << "\nThe file has been successfully opened for reading.\n\n";
outFile.open("blackbird_copy.txt");
if (outFile.fail())
{
cout << "The file was not successfully opened for writing" << endl;
exit(1);
}
cout << "The file has been successfully opened for writing.\n\n";
//outFile << "Hello";
// 1) this loop doesn't terminate. 2) the computer doesn't know what c1 is.
/*
while (inFile.get(c1))
{
outFile << c1;
cout << c1;
}
*/
// This one is no better
/*
while (inFile.good())
{
inFile.get(c);
outFile << c;
}
*/
inFile.close();
outFile.close();
// read contents of blackbird_copy to check our work.
inFile.open("blackbird_copy.txt");
while (inFile.get(c2))
{
cout << c2;
}
cout << endl << endl;
return 0;
}
inFile.get(c1) Reads one character and stores it to c1 if available. Otherwise, leaves ch unmodified and sets failbit and eofbit.
You can use inFile.eof() to check whether the end of the file has been reached.
I'm trying to write a multithreading program for a hw assignment. So far, all I've got in my program is some code to read a set of binary data files (provided for the assignment), and read the contents of those files into a 2D data array. The program builds without any errors, but when I run it, it exits after reading the names of the DAT files from a specified metadata file. I cannot figure out where I'm going wrong, and any help will be appreciated!
This is the error I receive:
"Unhandled exception at 0x773a5c0c (ntdll.dll) in MultiThreading.exe: 0xC0000374: A heap has been corrupted."
Followed by:
"Unhandled exception at 0x7730d1ed (ntdll.dll) in MultiThreading.exe: 0xC0000005: Access violation reading location 0x0000001e."
This is my code, and I'm positive there's an error in there somewhere, but I'm new to C++ programming and I can't find it :-/
// MultiThreading.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <Windows.h>
//include the custom header file
//#include <Engine.h>
using namespace std;
using namespace System;
using namespace System::Threading;
void ReadData(char * filename, int * nVals, float ** dataVals);
int ReadMeta(char * metaFile, int * nThreads, int * nFiles, string ** filenames);
void main(int argc, char * argv[])
{
//set default # of threads in case no user input is provided
int nThreads = 12;
//assign default metainfo file in case no user input is provided
char metaFile[200] = "DataFiles\\MetaInfo.txt";
//check for console user input for threads and metainfo file, if available
if (argc > 1)
{
nThreads = atoi(argv[1]);
if (argc > 2)
{
strcpy_s(metaFile, argv[2]);
}
}
//initialize # of files and string to hold filenames
int nFiles = 0;
string * filenames = NULL;
//read metainfo to get # of data files and file names
//Call ReadMeta(metaFile, &nThreads, &nFiles, &filenames);
//check for errors in reading metainfo
if (ReadMeta(metaFile, &nThreads, &nFiles, &filenames) == 0)
{
cout << "Error reading data files and/or requesting threads."
<< "\nOperation aborted!\n\n";
}
//read file data into multiple arrays
for (int i = 0; i < nFiles; i++)
{
cout << "Reading contents of data file " << filenames[i];
int nVals = NULL;
float * dataArray = NULL;
//convert string to char for filename to pass to function
char * binFile = (char*)filenames[i].c_str();
//read files and write to dataArray
ReadData(binFile, &nVals, &dataArray);
}
//release memory
if (filenames) delete[] filenames;
filenames = NULL;
system("pause");
}
int ReadMeta(char * metaFile, int * nThreads, int * nFiles, string ** filenames)
{
ifstream inputFile(metaFile);
//check for error locating metainfo file
if (!inputFile)
{
cout << "ERROR: Target file " << metaFile << " was not found.\n";
return 0;
}
//assign # of files to *nFiles
inputFile >> (*nFiles);
//check if data files are listed in metainfo file
if (*nFiles < 1)
{
cout << "No data files are provided!\n";
inputFile.close();
return 0;
}
else if (*nFiles < 2)
{
cout << "NOTE: Only ONE data file is available.\n\n";
}
//print number of data files to screen
else
{
cout << *nFiles << " data files are available.\n\n";
}
//check for # of threads being requested and set to default value if reqd
if ((*nThreads <= 0) || (*nThreads > *nFiles))
{
cout << "WARNING: Invalid number of threads requested.\n"
<< "Number of threads truncated to valid range 2 - " << *nFiles
<< "\nDefault value is 2 threads.";
*nThreads = 2;
}
//print # of data files and threads to screen
cout << *nFiles << " files are available.\n"
<< *nThreads << " threads have been requested.\n"
<< "Each file is assigned to a separate thread.\n";
//adjust number of threads
if (*nThreads > *nFiles)
{
*nThreads = *nFiles;
cout << "Fewer threads will be created due to insufficient data files."
<< "That is, only " << *nThreads << " threads will be created.\n\n";
}
else if (*nThreads < *nFiles)
{
*nFiles = *nThreads;
cout << "Fewer files will be used to meet the thread requirements."
<< "That is, only " << *nFiles << " files will be used for "
<< *nThreads << " threads.\n\n";
}
//assign file names to *filenames
*filenames = new string[*nFiles];
for (int i = 1; i <= (*nFiles); i++)
{
inputFile >> (*filenames)[i];
cout << "\nData file #" << i << ": " << (*filenames)[i].c_str() ;
}
//close metainfo file
inputFile.close();
cout << endl << endl;
return 1;
}
void ReadData(char * filename, int * nVals, float ** dataVals)
{
//open the file "filename" passed to the function
FILE * thisFile;
fopen_s(&thisFile, filename, "rb");
//read the number of values contained in the file
fread(nVals, sizeof(int), 1, thisFile);
//create an exact sized array to hold the values contained in the file
*dataVals = new float[*nVals];
//read values from file to array
fread(*dataVals, sizeof(float), *nVals, thisFile);
//close the file
fclose(thisFile);
}
I'm using Visual Studio Community 2015 on a Windows 10 x64 system. The program is configured for Win32.
Absolutely ANY help or any directions that can help me fix this will be greatly, greatly appreciated.
Thanks!
*filenames = new string[*nFiles];
for (int i = 1; i <= (*nFiles); i++)
{
inputFile >> (*filenames)[i];
cout << "\nData file #" << i << ": " << (*filenames)[i].c_str() ;
}
Arrays in C++ start with index of 0. An array filename containing five elements contains elements filename[0] through filename[4].
In this case, you would allocate an array of five strings, but instead of initializing filename[0] through filename[4], you will attempt to initialize filename[1] through filename[5].
Since filename[5] does not exist, this result in undefined behavior. A runtime crash that you've observed is one of the likely results from this undefined behavior.
The following C++ code is to read a txt file and then write the numbers of chars in each line and the number of all chars in the txt file.I use MS Visual Studio 2008.But something is wrong.Only the number of all chars is input into the txt files,but the numbers of each line are not input into the txt files.Now I cannot figure it out.Could someone give me some advice?Thanks a lot!
And my another question is what should I do to insert something in the middle of the txt file?
This is my Code:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream inOut("copy.txt",ios::in | ios::out | ios::app);
if (!inOut)
{
cerr << "ERROR:cannot open file!" << endl;
return -1;
}
int cnt = 0;
char ch;
inOut.seekg(0);
while(inOut.get(ch))
{
cout.put(ch);
++cnt;
if ('\n' == ch)
{
ios::pos_type mark = inOut.tellg();
if (!inOut)
{
cerr << "ERROR!" << endl;
return -1;
}
inOut << cnt;
inOut.put(' ');
inOut.seekg(mark);
}
}
inOut.clear();
inOut << cnt << endl;
cout << "[" << cnt << "]" << endl;
}
The txt file before running:
The txt file after running:
The result in command line:
I don't know fstream's very well, but I think you want to change the way you are doing this. You can think of a file as a contiguous piece of memory. Appending on the end is easy, but inserting in the middle can be problematic. In particular, if you do insert something, then your seekg might not be valid.
I would recommend three strategies:
Understand what is going on currently (try closing file before seekg and see if anything gets written by the inOut << cnt;)
Read from one file, write to a different file -- this will most likely be more efficient and less complicated than trying to modify the file in place.
Read from source file, store and modify in memory, write out modified buffer to original file. For large files, this might be less efficient than #2, but it means you don't need two files on disk.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
fstream inOut("copy.txt",ios::in | ios::out | ios::app);
if (!inOut)
{
cerr << "ERROR:cannot open file!" << endl;
return -1;
}
int cnt = 0;
int cntline=0;
char ch;
inOut.seekg(0);
while(inOut.get(ch))
{
cout.put(ch);
//++cnt it include '\n' it should put behind of "if"
if ('\n' == ch)
{ ios::pos_type mark = inOut.tellg();
if (!inOut)
{
cerr << "ERROR!" << endl;
return -1;
}
cntline=cnt-cntline; //add it to account the number of chars of each line
inOut.seekg(0,ios::end); //here!!!!!!!!!!!!!!!!!!!!!!!!!!! add this , the resault is finally right! the reason it's down here.
inOut << cntline;
cntline=cnt; // and here! it can assure the number of the chars of each line be right!
inOut.put(' ');
inOut.seekg(mark);
}
else
{
++cnt; // it's here!
}
}
inOut.clear();
inOut << cnt << endl;
cout << "[" << cnt << "]" << endl;
}
inOut.seekg(0,ios::end)
i'am not sure it,but you can take it a reference.
you open file with "ios::app",so the VS 2008 only allows you to add text start from the end of file (it won't happened in vc 6.0).
if the file is :
it's compile by
vs 2008
when get the first '\n' the file pointer is pointing to'vs 2008'(yes,it just like the common pointer point the string ). and i debug it then find a value of the stream object named _Wrotesome .its value is false!
so i think the compiler think the file pointer point at o const sting.so you just can't write anything whis this position. so i add the code inOut.seekg(0,ios::end);.now you
can write anything you want to this text!
wish this can help you !
I don't know why do you choose std::fstream as your tool. If std::fstream is not asked or necessary, I would like to provide a example to solve your problem. Here's some limitation:
a. I read all the file into memory in one ReadFile operation. If your file is large, you may replace it with a loop.
b. I suppose your line separator is '\n'.
c. I add [line_count] before the '\n', which look like better.
here's my code.
#include "windows.h"
#include "sstream"
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = ::CreateFile(L"C:\\Users\\wujian\\Desktop\\pingback - Copy.log", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE )
{
DWORD dwSize = ::GetFileSize(hFile, NULL);
if (dwSize)
{
char *pBuffer = new char[dwSize];
DWORD dwRead = 0;
::ReadFile(hFile, pBuffer, dwSize, &dwRead, NULL);
if (dwRead == dwSize)
{
std::stringstream ss;
int iPos = 0;
int iLine = 0;
while (iPos < dwSize)
{
if (pBuffer[iPos] == '\n')
{
ss << '[' << iLine << ']';
iLine = 0;
}
ss << pBuffer[iPos];
iPos ++, iLine ++;
}
ss << '[' << dwSize << ']';
::SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
DWORD dwWrite = 0;
::WriteFile(hFile, ss.str().c_str(), ss.str().length(), &dwWrite, NULL;
}
::CloseHandle(hFile);
}
}
return 0;
}