in this function where i am trying to write something on a disk, how can i check if the part of the disk is empty and it's safe to write on that part so i wouldn't lose data.
i tried finding answer to this and saw peek function but it seems that it's not working with that, I get an error with it
void write_sector(int num){
char diskName[] = "/dev/sda"; //disk name
std::ofstream disk(diskName, std::ios_base::binary); //opening the disk for output
std::string diskError = std::string() + diskName + ": ";
if(!disk){
throw(std::runtime_error(diskError + std::strerror(errno)));
}
disk.seekp(512 * num); //changing position to specific sector
if(!disk){
throw(std::runtime_error(diskError + std::strerror(errno)));
}
disk << "MAGIC"; //writing in sector
if(!disk){
throw(std::runtime_error(diskError + std::strerror(errno)));
}
disk.close();
}
Related
I've been staring at this to long...
I have made a program that logs weather data from different sensors. It handles the data in a double linkedlist and saves it to a binary file. To store different "compressions" of the data different files are used. e.g no compression, hours, days, etc.
The main program first loads the content of the correct file (defined by the WeatherSeries constructor) and adds all content from the file into the linkedlist. Then adds the new element and then saves it all. It adds to the list from oldest to newest and in the file it is also saved so the newest record is the last to be added to the file.
The error that occurs is that it seems that I lose a couple of hours of recorded data. I have observed that the data have existed. I.e. seen that there were data recorded between e.g. 9PM and 10PM and then in the morning after this data is gone.
The weird thing is the following:
Error only occurs intermittent and only for the barometric sensor that delivers values with 6 digits compared to the humidity and temperature sensors which delivers values with four digits.
It has only happened to the "no compression" and never for any of the other compressions. This means that the program that retrieves the data from the sensors works. Also it means that the function that adds data to the double linkedlist works.
Left is the functions that opens and saves the data to the files.
Can you please see if you can find any errors in my code?
void weatherSeries::saveSeries()
{
ostringstream s;
s << "WLData/" << mSensorNbr << "_" << mSensorType << "_" << mTimeBase << ".dat";
ofstream file(s.str().c_str(), ios::out | ios::trunc | ios::binary);
if (!file)
{
file.clear();
file.open(s.str().c_str(), ios::out | ios::trunc | ios::binary);
}
if(file.is_open())
{
for (current = tail; current != NULL; current = current->prev)
{
file.write((char*)¤t->time_stamp, sizeof(time_t));
file.write((char*)¤t->val_avg, sizeof(double));
file.write((char*)¤t->min, sizeof(double));
file.write((char*)¤t->max, sizeof(double));
file.write((char*)¤t->nbrOfValues, sizeof(unsigned long int));
}
}
else
{
cerr << "Unable to open for saving to " << mSensorNbr << "_" << mSensorType << "_" << mTimeBase << ".dat";
}
file.close();
}
void weatherSeries::openSeries()
{
deleteAll();
ostringstream s;
s << "WLData/" << mSensorNbr << "_" << mSensorType << "_" << mTimeBase << ".dat";
ifstream file(s.str().c_str(), ios::in | ios::binary);
if (!file)
{
file.clear();
file.open(s.str().c_str(), ios::in | ios::binary);
}
if(file.is_open())
{
time_t tmp_TS = 0;
double tmp_val_avg = 0;
double tmp_min = 0;
double tmp_max = 0;
unsigned long int tmp_nbrOfValues = 0;
while (file.read((char*)&tmp_TS, sizeof(time_t)))
{
file.read((char*)&tmp_val_avg, sizeof(double));
file.read((char*)&tmp_min, sizeof(double));
file.read((char*)&tmp_max, sizeof(double));
file.read((char*)&tmp_nbrOfValues, sizeof(unsigned long int));
addToSeries(tmp_TS, tmp_val_avg, tmp_min, tmp_max, tmp_nbrOfValues, true);
}
}
else
{
cerr << "Unable to open for opening from " << mSensorNbr << "_" << mSensorType << "_" << mTimeBase << ".dat";
}
file.close();
}
Note: deleteAll() clears the double linkedlist.
You were correct. The error was found in another part of the program. When I started logging different things in the code.
More or less different mechanism instantiate the program and it happened to happen at the same time causing the file to be manipulated by to instances at the same time.
I have been experiencing a bug for the past day that I have not been able to solve.
I have my first method which is for saving player data:
bool Player::savePlayerData() {
ofstream writeFile(getName() + ".bin", ios::out | ios::binary | ios::trunc);
string writeData;
writeData = formatEntityData() + "<" + formatLocationData() + "<" + formatInventory();
writeFile.write(writeData.c_str(), writeData.length() + 1);
writeFile.close();
return true;
}
Note: Assume that getName(), formatEntityData(), formatLocationData(), and formatInventory() return strings and are functional.
Then I have my load player data method:
bool Player::loadPlayerData(string name) {
ifstream readFile(name + ".bin", ios::in | ios::binary | ios::_Nocreate);
if (readFile.good() && readFile.is_open()) {
string data;
getline(readFile, data, '\0');
vector<string> str = split(data, '<');
parseEntityData(str.at(0));
parseLocationData(str.at(1));
parseInventory(str.at(2));
readFile.close();
return true;
}
readFile.close();
return false;
}
Note: Assume that parseEntityData(), parseLocationData(), parseInventory() have string param, void returns and are functional
Note: Assume that split(string, char) takes in a string with a delim. char and splits into vector correctly
So, here is what I am trying to accomplish (for purposes of simplicity lets assume getName() return "luke"):
•Create luke.bin
•Save string to luke.bin in binary
•Load data from luke.bin in form of a string
When I run the program is not properly reading the player data. Instead it is returning as if nothing is in the file. What am I doing wrong? Any tips, ideas, or thoughts would be greatly appreciated.
Code on brothers!
Typically when you open a binary file in notepad++ it gives seemingly
random characters
It depends on data. The string "Hell world" is the same in binary or text. Numbers will appear as text if they are text formatted.
Example of text format:
fout << 1234 << std::endl; //saved as "1234"
Example of binary data:
int i = 1234;
fout.write(&i, sizeof(i)); //saved as 2 bytes, big-endian or little endian binary
ios::binary stops translation of new line characters.
When writing to file, put the exact size:
writeFile.write(writeData.c_str(), writeData.length());
When reading the file, getline(fin, data, '\0'); will stop when it reaches zero or end of file. You should use EOF instead of zero. Better yet, use this method:
std::ifstream f(filename, ios::binary);
if (f.good())
{
f.seekg(0, ios::end);
size_t filesize = (size_t)f.tellg();
f.seekg(0);
std::string data(filesize, 0);
f.read(&data[0], filesize);
cout << data << endl;
return true;
}
return false;
I got a small problem.. Currently im writing a small tool which connects to a Server, downloads some blowfish encrypted Data into a char Array (char buffer[512]) and saves that Array into a file (fstream ios::binary).
Then later i reopen that file (ifstream ios::binary) and send it back. This time i read it into a std::string and not a char[].
My Problem now is that the Data is corrupted after i send them back.
What would be the best way to acomblish this? Is it safe to use char[] and std::string? Or does that somehow corrupt the data? (i guess so).
If you need some code examples i can provide them.
Thanks!
##########################
Okay a quick update to give you more details.
Im writing a Tool for a game (on OS X), its seperated in two parts:
Retrieve the encrypted Data from Game Servers and save them.
Send the saved encrypted Data back to the local Game
Problem: When the saved Data arrives the local Game, the Game just spits out that the Data cant be decrypted => data corruption.
Here's the code for 1. (Its just poc for selftesting purpose):
mode == 0 => no gameDataChunk there
mode == 1 => gameDataChunk there, need to write
mode == 2 => keyFrame there
*/
std::string socketRead(int socket, int mode, std::string num_chunk, std::string num_key, std::string game_id){
std::string response = "";
char buffer[512];
int bytes;
while((bytes = read(socket, buffer, 511)) > 0){
std::string temp(buffer, bytes);
//std::cout << temp;
response = response + temp;
if(!(temp.find("HTTP/1.1 200")<1800000)){
if(temp.find("HTTP/1.1")<1800000){
std::cout << std::endl << std::endl << "GOT NOT A 200 !!!" << std::endl << std::endl;
std::cout << temp << std::endl << std::endl;
return "EXIT";
}
}
if(mode == 1){
if(temp.find("\r\n\r\n")<1800000){
write_gameDataChunk(buffer, 1, temp.find("\r\n\r\n")+4, num_chunk, game_id);
}
else{
write_gameDataChunk(buffer, 0, 0, num_chunk, game_id);
}
}
else if(mode == 2){
if(temp.find("\r\n\r\n")<1800000){
write_keyFrame(buffer, 1, temp.find("\r\n\r\n")+4, num_key, game_id);
}
else{
write_keyFrame(buffer, 0,0, num_key, game_id);
}
}
bzero(buffer, 512);
}
return response;
}
void write_gameDataChunk(char buffer[], int mode, int index, std::string num, std::string game_id){
std::fstream write;
char local_buffer[512];
if(mode == 0){
//complete bin data
write.open("/tmp/" + game_id + "/" + num + "/game_dataChunk.bin", std::ios::out | std::ios::binary | std::ios::app);
write << buffer;
}
else if(mode == 1){
//partial bin data
std::string command = "mkdir /tmp/" + game_id + "/" + num;
std::system(command.c_str());
write.open("/tmp/" + game_id + "/" + num + "/game_dataChunk.bin", std::ios::out | std::ios::binary);
strcpy(local_buffer, buffer+index);
write << local_buffer;
}
write.close();
}
Here is the code for 2.:
std::string get_DataChunk(std::string game_id, int chunkId){
std::ifstream read;
std::string dummy;
std::string command;
std::string result = "";
command = "/tmp/" + game_id + "/" + std::to_string(chunkId) + "/game_dataChunk.bin";
read.open(command.c_str(), std::ios::in | std::ios::binary);
while(getline(read,dummy)){
result = result + dummy;
}
read.close();
return result;
}
This is all testing code for myself and not finished, so its kinda ugly... but i hope you will understand what i mean. I did not often had to deal with binary Data send over Sockets..
std::string is not meant to deal with binary. It is meant to deal with strings.
What you want is a std::vector<char> which doesn't care about what values you are storing.
Any '\0' in your binary data will stop construct the std::string. So the std::string().size() only count to the character before 1st '\0'. Use std::vector<unsigned char> instead.
By the way, what does 1800000 mean? I know that HTTP/1.1 200 is the characters you received at the earliest.(poor english)
I'm new to the forum, but not to this website. I've been searching for weeks on how to process a large data file quickly using C++ 11. I'm trying to have a function with a member that will capture the trace file name, open and process the data. The trace file contains 2 million lines of data, and each line is structured with a read/write operation and a hex address:
r abcdef123456
However, with a file having that much data, I need to read in and parse those 2 values quickly. My first attempt to read the file was the following:
void getTraceData(string filename)
{
ifstream inputfile;
string file_str;
vector<string> op, addr;
// Open input file
inputfile.open(filename.c_str());
cout << "Opening file for reading: " << filename << endl;
// Determine if file opened successfully
if(inputfile.fail())
{
cout << "Text file failed to open." << endl;
cout << "Please check file name and path." << endl;
exit(1);
}
// Retrieve and store address values and operations
if(inputfile.is_open())
{
cout << "Text file opened successfully." << endl;
while(inputfile >> file_str)
{
if((file_str == "r") || (file_str == "w"))
{
op.push_back(file_str);
}
else
{
addr.push_back(file_str);
}
}
}
inputfile.close();
cout << "File closed." << endl;
}
It worked, it ran, and read in the file. Unfortunately, it took the program 8 minutes to run and read the file. I modified the first program to the second program, to try and read the file in faster. It did, reading the file into a buffer in a fraction of a second versus 8 mins. using ifstream:
void getTraceData()
{
// Setup variables
char* fbuffer;
ifstream ifs("text.txt");
long int length;
clock_t start, end;
// Start timer + get file length
start = clock();
ifs.seekg(0, ifs.end);
length = ifs.tellg();
ifs.seekg(0, ifs.beg);
// Setup buffer to read & store file data
fbuffer = new char[length];
ifs.read(fbuffer, length);
ifs.close();
end = clock();
float diff((float)end - (float)start);
float seconds = diff / CLOCKS_PER_SEC;
cout << "Run time: " << seconds << " seconds" << endl;
delete[] fbuffer;
}
But when I added the parsing portion of the code, to get each line, and parsing the buffer contents line-by-line to store the two values in two separate variables, the program silently exits at the while-loop containing getline from the buffer:
void getTraceData(string filename)
{
// Setup variables
char* fbuffer;
ifstream ifs("text.txt");
long int length;
string op, addr, line;
clock_t start, end;
// Start timer + get file length
start = clock();
ifs.seekg(0, ifs.end);
length = ifs.tellg();
ifs.seekg(0, ifs.beg);
// Setup buffer to read & store file data
fbuffer = new char[length];
ifs.read(fbuffer, length);
ifs.close();
// Setup stream buffer
const int maxline = 20;
char* lbuffer;
stringstream ss;
// Parse buffer data line-by-line
while(ss.getline(lbuffer, length))
{
while(getline(ss, line))
{
ss >> op >> addr;
}
ss.ignore( strlen(lbuffer));
}
end = clock();
float diff((float)end - (float)start);
float seconds = diff / CLOCKS_PER_SEC;
cout << "Run time: " << seconds << " seconds" << endl;
delete[] fbuffer;
delete[] lbuffer;
}
I was wondering, once my file is read into a buffer, how do I retrieve it and store it into variables? For added value, my benchmark time is under 2 mins. to read and process the data file. But right now, I'm just focused on the input file, and not the rest of my program or the machine it runs on (the code is portable to other machines). The language is C++ 11 and the OS is a Linux computer. Sorry for the long posting.
Your stringstream ss is not associated to fbuffer at all. You are trying to getline from an empty stringstream, thus nothing happens. Try this:
string inputedString(fbuffer);
istringstream ss(fbuffer);
And before ss.getline(lbuffer, length), please allocate memory for lbuffer.
Actually you can directly read your file into a string to avoid the copy construction. Check this Reading directly from an std::istream into an std::string .
Last but not least, since your vector is quite large, you'd better reserve enough space for it before push_back the items one by one. When a vector reaches its capacity, attempt to push_back another item into it will result in reallocation and copy of all previous items in order to ensure continuous storage. Millions of items will make that happen quite a few times.
I am creating a very simple webserver, as practice in C++ and sockets. I use OSX.
The code sample is from inside the while(1) loop, a connection has been made and I am starting to process the header. This code works for all text-files but it dosn't work with images. And I figure that I can't use the same method to read text-files and images since images isn't separeted with lines. But how do I read the image data to send through the socket? I might not even be able to use a string, do I have to use char*?
string strFile = "htdocs" + getFileFromHeader(httpRequestHeader);
string strExt = getFileExtension(strFile);
string httpContent = "";
ifstream fileIn(strFile.c_str(), ios::in); // <-- do I have to use ios::binary ?
if(!fileIn)
{
// 404
cout << "File could not be opened" << endl;
httpContent = httpHeader404;
}
else
{
// 200
string contentType = getContentType(strExt);
cout << "Sending " << strFile << " -- " << contentType << endl;
string textInFile = "";
while (fileIn.good())
{
getline (fileIn, textInFile); // replace with what?
httpContent = httpContent + textInFile + "\n";
}
httpContent = httpHeader200 + newLine + contentType + newLine + newLine + httpContent;
}
// Sending httpContent through the socket
The question is about how to read the image data.
*EDIT 2011-05-19 *
So, this is an updated version of my code. The file have been opened with ios::binary, however, there are more problems.
httpContent = httpHeader200 + newLine + contentType + newLine + newLine;
char* fileContents = (char*)httpContent.c_str();
char a[1];
int i = 0;
while(!fileIn.eof())
{
fileIn.read(a, 1);
std::size_t len = std::strlen (fileContents);
char *ret = new char[len + 2];
std::strcpy ( ret, fileContents );
ret[len] = a[0];
ret[len + 1] = '\0';
fileContents = ret;
cout << fileContents << endl << endl << endl;
delete [] ret;
i++;
}
The problem is that is seems that the char * fileContents empty itself every ~240 chars. How can that be? Is there some sort of limit to some of theese functions that they only accept certain length?
Open the file for binary read, store the data in a char* array large enough, then send that array.
As #Blackbear said, but don't forget to send the corresponding HTML-Headers like contentEncoding, transferEncoding, etc. For simplicity try to send the binary Data of the image encoded in base64.