std::fstream saves variable to file wrong - c++

Problem solved! Thanks to #ewindes! I may go further with mu project! Bug in Notepad++ Hex Editor Plugin v0.9.5. I open with WinHex and Xplore and see 79 00 00 10. I trust too match...
I expect see in hex editor 79 00 00 10 but see 79 e1 80 80.
Using codeblocks with mingw 5.3.0. Tried visual studio 10 and got same result.
Why can't save variable right?
Code is simple and looks correct:
#include <iostream>
#include <fstream>
#include <stdint.h>
using namespace std;
const uint32_t uid1 = 0x10000079;
int main()
{
std::fstream fs;
fs.open("e32.exe", std::fstream::trunc | std::fstream::binary | std::fstream::out);
fs.write((const char*)&uid1, sizeof(uid1));
fs.close();
cout << "Hello world!" << endl;
cout << "sizeof(uid1): " << sizeof(uid1) << endl;
return 0;
}
I play more with code and got very strange results. File "test" contain crap as above:
FILE *fp;
if((fp=fopen("test", "wb"))==NULL) {
printf("Cannot open file.");
return 1;
}
char *data = (char *)&uid1;
fwrite(&data[0], 1, 1, fp);
printf("data[0] %x\n", data[0]);
fwrite(&data[1], 1, 1, fp);
printf("data[1] %x\n", data[1]);
fwrite(&data[2], 1, 1, fp);
printf("data[2] %x\n", data[2]);
fwrite(&data[3], 1, 1, fp);
printf("data[3] %x\n", data[3]);
fclose (fp);
But uid1 contain valid data:
data[0] 79
data[1] 0
data[2] 0
data[3] 10

Bug in Notepad++ Hex Editor Plugin v0.9.5. I open with WinHex and Xplore and see 79 00 00 10. I trust that too match...

Related

QDataStream reads and writes more bytes than QFile::length() reports to have

I have a utility that should copy files from one location to another.
The problem I have is when reading X bytes using the QDataStream and writing it, the number of bytes being read/written exceeds the number of bytes the file has. I see this problem happen with a number of files.
I am using a QDataStream::readRawData() and QDataStream::writeRawData() to facilitate reading/writing to and from files as shown below
QDataStream in(&sourceFile);
QDataStream out(&newFile);
// Read/Write byte containers
qint64 fileBytesRead = 0;
quint64 fileBytesWritten = 0;
qint64 bytesWrittenNow = 0;
quint8* buffer = new quint8[bufSize];
while ((fileBytesRead = in.readRawData((char*)buffer, bufSize)) != 0) {
// Check if we have a read/write mismatch
if (fileBytesRead == -1) {
printCritical(TAG, QString("Mismatch read/write: [R:%1/W:%2], total file write/max [W:%3/M:%4]. File may be corrupted, skipping...").arg(QString::number(fileBytesRead), QString::number(bytesWrittenNow), QString::number(fileBytesWritten), QString::number(storageFile.size)));
// close source file handle
sourceFile.close();
// Close file handle
newFile.close();
return BackupResult::IOError;
}
// Write buffer to file stream
bytesWrittenNow = out.writeRawData((const char*)buffer, fileBytesRead);
// Check if we have a read/write mismatch
if (bytesWrittenNow == -1) {
printCritical(TAG, QString("Mismatch read/write: [R:%1/W:%2], total file write/max [W:%3/M:%4]. File may be corrupted, skipping...").arg(QString::number(fileBytesRead), QString::number(bytesWrittenNow), QString::number(fileBytesWritten), QString::number(storageFile.size)));
// close source file handle
sourceFile.close();
// Close file handle
newFile.close();
return BackupResult::IOError;
}
// Add current buffer size to written bytes
fileBytesWritten += bytesWrittenNow;
if(fileBytesWritten > storageFile.size) {
qWarning() << "Extra bytes read/written exceeding file length"; <================= this line is hit every now and then
}
//...
This problem isn't consistent, but it happens every now and then, I have no idea why. Anyone have thoughts on a possible cause?
The name of the function QDataStream::writeRawData() sounds like ideal for writing binary data. Unfortunately, that's only half of the story.
The open-mode of the file is relevant as well under certain conditions – e.g. if the QFile is opened on Windows with QIODevice::Text:
QIODevice::Text
When reading, the end-of-line terminators are translated to '\n'. When writing, the end-of-line terminators are translated to the local encoding, for example '\r\n' for Win32.
I prepared an MCVE to demonstrate that:
// Qt header:
#include <QtCore>
void write(const QString &fileName, const char *data, size_t size, QIODevice::OpenMode mode)
{
qDebug() << "Open file" << fileName;
QFile qFile(fileName);
qFile.open(mode | QIODevice::WriteOnly);
QDataStream out(&qFile);
const int ret = out.writeRawData(data, size);
qDebug() << ret << "bytes written.";
}
// main application
int main(int argc, char **argv)
{
const char data[] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f'
};
const size_t size = sizeof data / sizeof *data;
write("data.txt", data, size, 0);
write("test.txt", data, size, QIODevice::Text);
}
Built and tested in VS2017 on Windows 10:
Open file "data.txt"
16 bytes written.
Open file "test.txt"
16 bytes written.
Result inspected with the help of cygwin:
$ ls -l *.txt
-rwxrwx---+ 1 scheff Domänen-Benutzer 427 Jun 23 08:24 CMakeLists.txt
-rwxrwx---+ 1 scheff Domänen-Benutzer 16 Jun 23 08:37 data.txt
-rwxrwx---+ 1 scheff Domänen-Benutzer 17 Jun 23 08:37 test.txt
$
data.txt has 16 bytes as expected but test.txt has 17 bytes. Oops!
$ hexdump -C data.txt
00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
00000010
$ hexdump -C test.txt
00000000 00 01 02 03 04 05 06 07 08 09 0d 0a 0b 0c 0d 0e |................|
00000010 0f |.|
00000011
$
Obviously, the underlying Windows file function “corrected” the \n to \r\n – 09 0a 0b became 09 0d 0a 0b. Hence, there occurs one additional byte which was not part of the originally written data.
Similar effects may happen when the QFile is opened for reading with QIODevice::Text involved.

Custom binary file triggers failbit in c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
tl;dr: What are necessary control characters that custom file must have in order not to trigger [or trigger] badbit, failbit, badbit, eofbit dependant on OS?
I am working with Cygwin and Notepad++, using Windows 7 on an x64 laptop.
I have an file called genesis.o that I typed in hex editor that is in same directory as sandbox.cpp from which I am doing reading/writing. The file "genesis.o" contains:
genesis.o
-----------------
58 - 4f - 58 - 4f
58 - 58 - 58 - 58
3f - 3f - 3f - 3f
00 - 00 - 00 - 3f
00 - 00 - 3f - 00
00 - 3f - 00 - 00
3f - 00 - 00 - 00
00 - 00 - 00 - 58
00 - 00 - 58 - 00
00 - 58 - 00 - 00
58 - 00 - 00 - 00
48 - 45 - 4c - 4c
So far, I have read and manipulated custom structures without any regard of validity of the file. I used stat to check if file is accessible and that was enough.
This file (with and without extension ".o") passes all check ups I made except file.rdstate in which it always returns 4 (std::ios::failbit).
Error doesn't show itself on any other normal file, so I am guessing that some sort of control character sequence before/after or in file actually tells the std::fstream that file is valid.
Since no other file (except those typed in a hex editor) triggers this behaviour, is there a way to structure an custom binary file to be recognised by fstream? Some sort of control characters, preset flags etc.?
I am using std::ios:in | std::ios:binary. I am reading it by getting stat buffer.st_size -> divide it by 4 (since I read 4 byte integers) and:
uitn32_t temp = 0;
file.read( (char *)(&temp), sizeof(uint32_t) );
It is notable to mention, that I can read that binary file even if file.rdstate returns an failbit.
Minimal testable example. Just make an "genesis.o" file with character specification above.
#include <fstream>
#include <iostream>
#include <string>
#include <sys\types.h>
#include <sys\stat.h>
#include <vector>
struct handl{
std::string name = "genesis";
std::string ext = "o";
std::vector<uint32_t> mem;
bool acces = false;
struct stat buffer;
handl():mem(0),name("genesis"),ext("o"){}
const char *f_name(){
std::string f_n = this->name;
f_n.append(".");
f_n.append(this->ext);
return f_n.c_str();
}
void recheck(){
this->acces = ( stat(this->f_name(), &this->buffer ) == 0 );
}
virtual bool header( std::fstream &file )
{return true;}
virtual bool footer( std::fstream &file )
{return true;}
void operator()(){ this->recheck(); }
void operator()( const char *name, const char *ext ){
this->name = std::string(name);
this->ext = std::string(ext);
this->recheck();
}
void prefix( const char* pre ){
std::string pn(pre);
pn.append( this->name );
this->name = pn;
}
void suffix( const char *su ){
this->name.append(su);
this->recheck();
}
int read(){
this->recheck();
if( !this->acces ){return 0;}
std::fstream file;
file = std::fstream( this->f_name(), std::ios::in | std::ios::binary );
if( this->header(file) && this->footer(file) ){
int byte_size = this->buffer.st_size;
std::cout << file.rdstate() << std::endl;
std::cout << "gb\t" << std::ios::goodbit << std::endl;
std::cout << "bb\t" << std::ios::badbit << std::endl;
std::cout << "eb\t" << std::ios::eofbit << std::endl;
std::cout << "fb\t" << std::ios::failbit << std::endl;
file.close();
return 1;
}else{
file.close();
return 0;
}
}
};
int main(){
handl f;
std::cout << f.read() << std::endl;
return 0;
}
return f_n.c_str();
Your local f_n object is destroyed and the pointer to its internal memory is dangling. Using it is undefined behaviour. File content is irrelevant.
I tried your code, and this line: if( !this->acces ){return 0;} is failing for me. By "failing", I mean this is causing the read function to return 0.

StreamTransformationFilter: invalid PKCS #7 block padding found using AES decryption

I am trying to perform AES decryption using the crypto++ library. I have an encrypted file whose first 8 bytes are the filelength, subsequent 16 bytes are the initialization vector, and the remaining data is the data of interest. I also have a string representation of my key (which I hash using SHA256)
I get the following error when trying to perform AES decryption:
StreamTransformationFilter: invalid PKCS #7 block padding found
I am using the following c++ code:
std::string keyStr = "my_key";
std::string infilePath = "my/file/path";
CryptoPP::SHA256 hash;
unsigned char digest[CryptoPP::SHA256::DIGESTSIZE];
hash.CalculateDigest( digest, reinterpret_cast<const unsigned char*>(&keyStr[0]), keyStr.length() );
auto key = CryptoPP::SecByteBlock(digest, CryptoPP::SHA256::DIGESTSIZE);
std::ifstream fin(infilePath, std::ifstream::binary);
// First 8 bytes is the file size
std::vector<char> fileSizeVec(8);
fin.read(fileSizeVec.data(), fileSizeVec.size());
// Read the next 16 bytes to get the initialization vector
std::vector<char> ivBuffer(16);
fin.read(ivBuffer.data(), ivBuffer.size());
CryptoPP::SecByteBlock iv(reinterpret_cast<const unsigned char*>(ivBuffer.data()), ivBuffer.size());
// Create a CBC decryptor
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryption;
decryption.SetKeyWithIV(key, sizeof(key), iv);
CryptoPP::StreamTransformationFilter decryptor(decryption);
std::vector<char> buffer(CHUNK_SIZE, 0);
while(fin.read(buffer.data(), buffer.size())) {
CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), buffer.size());
decryptor.Put(tmp, tmp.size());
}
decryptor.MessageEnd();
size_t retSize = decryptor.MaxRetrievable();
std::vector<char> decryptedBuff;
decryptedBuff.resize(retSize);
decryptor.Get(reinterpret_cast<CryptoPP::byte*>(decryptedBuff.data()), decryptedBuff.size());
I am not sure what is giving me the error. I am working off the following python code. When I run the python code with the same input file, it successfully decrypts the file.
def decrypt_file(in_filename, out_filename=None):
key = hashlib.sha256(PASSWORD).digest()
"""loads and returns the embedded model"""
chunksize = 24 * 1024
if not out_filename:
out_filename = os.path.splitext(in_filename)[0]
with open(in_filename, 'rb') as infile:
# get the initial 8 bytes with file size
tmp = infile.read(8)
iv = infile.read(16)
decryptor = AES.new(key, AES.MODE_CBC, iv)
string = b''
# with open(out_filename, 'wb') as outfile:
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
string += decryptor.decrypt(chunk)
return string
In addition to solving the error, I would also love some general c++ coding feedback on how I can improve.
Thanks in advance!
Edit:
It looks like I wasn't reading the input file all the way to the end (as the length of the last chunk is smaller than CHUNK_SIZE). The following code now reads the entire file, however I still get the same issue. I have also confirmed that the IV and key match exactly that produced from the python code.
// Get the length of the file in bytes
fin.seekg (0, fin.end);
size_t fileLen = fin.tellg();
fin.seekg (0, fin.beg);
std::vector<char> buffer(CHUNK_SIZE, 0);
size_t readSize = CHUNK_SIZE;
while(fin.read(buffer.data(), readSize)) {
CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), CHUNK_SIZE);
decryptor.Put(tmp, tmp.size());
std::fill(buffer.begin(), buffer.end(), 0);
size_t bytesReamining = fileLen - fin.tellg();
readSize = CHUNK_SIZE < bytesReamining ? CHUNK_SIZE : bytesReamining;
if (!readSize)
break;
}
}
Note that I have tried this line as both CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), CHUNK_SIZE);
and CryptoPP::SecByteBlock tmp(reinterpret_cast<const unsigned char*>(buffer.data()), readSize); (Using CHUNK_SIZE pads with 0)
I have an encrypted file whose first 8 bytes are the filelength, subsequent 16 bytes are the initialization vector, and the remaining data is the data of interest...
I think I'll just cut to the chase and show you an easier way to do things with the Crypto++ library. The key and iv are hard-coded to simplify the code. The derivation is not needed for the example. By the way, if Python has it, you should consider using HKDF for derivation of the AES key and iv. HKDF has provable security properties.
Crypto++ handles the chunking for you. You don't need to explicitly perform it; see Pumping Data on the Crypto++ wiki.
I believe the Python code has a potential padding oracle present due to the use of CBC mode without a MAC. You might consider adding a MAC or using an Authenticated Encryption mode of operation.
#include "cryptlib.h"
#include "filters.h"
#include "osrng.h"
#include "modes.h"
#include "files.h"
#include "aes.h"
#include "hex.h"
#include <string>
#include <iostream>
const std::string infilePath = "test.dat";
int main(int argc, char* argv[])
{
using namespace CryptoPP;
const byte key[16] = {
1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4
};
const byte iv[16] = {
8,7,6,5, 8,7,6,5, 8,7,6,5, 8,7,6,5
};
const byte data[] = // 70 characters
"Now is the time for all good men to come to the aide of their country.";
HexEncoder encoder(new FileSink(std::cout));
std::string message;
// Show parameters
{
std::cout << "Key: ";
StringSource(key, 16, true, new Redirector(encoder));
std::cout << std::endl;
std::cout << "IV: ";
StringSource(iv, 16, true, new Redirector(encoder));
std::cout << std::endl;
std::cout << "Data: ";
StringSource(data, 70, true, new Redirector(encoder));
std::cout << std::endl;
}
// Write sample data
{
FileSink outFile(infilePath.c_str());
word64 length = 8+16+70;
outFile.PutWord64(length, BIG_ENDIAN_ORDER);
outFile.Put(iv, 16);
CBC_Mode<AES>::Encryption enc;
enc.SetKeyWithIV(key, 16, iv, 16);
StringSource(data, 70, true, new StreamTransformationFilter(enc, new Redirector(outFile)));
}
// Read sample data
{
FileSource inFile(infilePath.c_str(), true /*pumpAll*/);
word64 read, l;
read = inFile.GetWord64(l, BIG_ENDIAN_ORDER);
if (read != 8)
throw std::runtime_error("Failed to read length");
SecByteBlock v(16);
read = inFile.Get(v, 16);
if (read != 16)
throw std::runtime_error("Failed to read iv");
CBC_Mode<AES>::Decryption dec;
dec.SetKeyWithIV(key, 16, v, 16);
SecByteBlock d(l-8-16);
StreamTransformationFilter f(dec, new ArraySink(d, d.size()));
inFile.CopyTo(f);
f.MessageEnd();
std::cout << "Key: ";
StringSource(key, 16, true, new Redirector(encoder));
std::cout << std::endl;
std::cout << "IV: ";
StringSource(v, 16, true, new Redirector(encoder));
std::cout << std::endl;
std::cout << "Data: ";
StringSource(d, d.size(), true, new Redirector(encoder));
std::cout << std::endl;
message.assign(reinterpret_cast<const char*>(d.data()), d.size());
}
std::cout << "Message: ";
std::cout << message << std::endl;
return 0;
}
Running the program results in:
$ g++ test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Key: 01020304010203040102030401020304
IV: 08070605080706050807060508070605
Data: 4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F2063
6F6D6520746F207468652061696465206F6620746865697220636F756E7472792E
Key: 01020304010203040102030401020304
IV: 08070605080706050807060508070605
Data: 4E6F77206973207468652074696D6520666F7220616C6C20676F6F64206D656E20746F2063
6F6D6520746F207468652061696465206F6620746865697220636F756E7472792E
Message: Now is the time for all good men to come to the aide of their country.
Prior to this Stack Overflow question, the Crypto++ library did not provide PutWord64 and GetWord64. Interop with libraries like Python is important to the project, so they were added at Commit 6d69043403a9 and Commit 8260dd1e81c3. They will be part of the Crypto++ 8.3 release.
If you are working with Crypto++ 8.2 or below, you can perform the 64-bit read with the following code.
word64 length;
word32 h, l;
inFile.GetWord32(h, BIG_ENDIAN_ORDER);
inFile.GetWord32(l, BIG_ENDIAN_ORDER);
length = ((word64)h << 32) | l;
Here is the data file used for this example.
$ hexdump -C test.dat
00000000 00 00 00 00 00 00 00 5e 08 07 06 05 08 07 06 05 |.......^........|
00000010 08 07 06 05 08 07 06 05 b0 82 79 ee a6 d8 8a 0e |..........y.....|
00000020 a6 b3 a4 7e 63 bd 9a bc 0e e4 b6 be 3e eb 36 64 |...~c.......>.6d|
00000030 72 cd ba 91 8d e0 d3 c5 cd 64 ae c0 51 de a7 c9 |r........d..Q...|
00000040 1e a8 81 6d c0 d5 42 2a 17 5a 19 62 1e 9c ab fd |...m..B*.Z.b....|
00000050 21 3d b0 8f e2 b3 7a d4 08 8d ec 00 e0 1e 5e 78 |!=....z.......^x|
00000060 56 6d f5 3e 8c 5f fe 54 |Vm.>._.T|
Looks like the issue had to do with padding. I instead switched to using a StringSource, which only worked once I specified CryptoPP::BlockPaddingSchemeDef::BlockPaddingScheme::ZEROS_PADDING as an argument for StreamTransformationFilter
Here is the working code for anyone that is interested:
void Crypto::decryptFileAES(CryptoPP::SecByteBlock key, std::string infilePath) {
std::ifstream fin(infilePath, std::ifstream::binary);
// Get the length of the file in bytes
fin.seekg (0, fin.end);
size_t fileLen = fin.tellg();
fin.seekg (0, fin.beg);
// First 8 bytes is the file size
std::vector<char> fileSizeVec(8);
fin.read(fileSizeVec.data(), fileSizeVec.size());
// Read the first 16 bytes to get the initialization vector
std::vector<char> ivBuffer(16);
fin.read(ivBuffer.data(), ivBuffer.size());
CryptoPP::SecByteBlock iv(reinterpret_cast<const unsigned char*>(ivBuffer.data()), ivBuffer.size());
// Create a CBC decryptor
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryption;
decryption.SetKeyWithIV(key, sizeof(key), iv);
size_t bytesReamining = fileLen - fin.tellg();
std::vector<char> buffer(bytesReamining);
if(!fin.read(buffer.data(), bytesReamining)) {
throw std::runtime_error("Unable to read file");
}
std::string decryptedText;
CryptoPP::StringSource ss(reinterpret_cast<const unsigned char*>(buffer.data()), buffer.size(), true,
new CryptoPP::StreamTransformationFilter(decryption,
new CryptoPP::StringSink(decryptedText), CryptoPP::BlockPaddingSchemeDef::BlockPaddingScheme::ZEROS_PADDING));
std::cout << decryptedText << std::endl;
}

C++: Trouble reading .BMP files; end of file reached earlier than expected

i am currently trying to read .BMP files using C++, but somehow after reading a few bytes the end of the file is reached (fgetc() returns -1). I've reduced the problem to a minimal example:
#include <iostream>
int main()
{
// Open file
FILE* file = fopen("C:/Path/to/file", "r");
// Get and print file size in bytes
fseek(file, 0L, SEEK_END);
std::cout << ftell(file) << std::endl;
rewind(file);
int byte, i = 0;
do
{
// Get each byte
byte = fgetc(file);
// Print i and value of byte
std::cout << i << ", " << byte << std::endl;
i++;
}
// Stop reading when end of file is reached
while (byte != EOF);
std::cin.get();
return 0;
}
When using this to read .BMP files (problem does not occur on simple formats like .txt files), It reads the file length correctly, but finds the EOF way before reaching the end of the file.
For example, using this file, it reads a file length of 120054, but fgetc() returns -1 at i=253.
What exactly am i doing wrong, and how can i fix this problem?
Reading a file in plain "r" mode on DOS/Windows may treat ASCII 26 (^Z) as "end of file". It may also convert line endings from CR LF (13 10) to LF (10), which you also don't want.
Looking at your sample file, I do indeed see that character (it's 1A in hex):
0000340 0c 1f 15 0e 1f 15 0e 1f 14 10 1f 14 10 21 17 10
0000360 21 17 10 22 18 11 23 19 12 25 19 13 26[1a]14 26
The position is 375 octal, which is 253 decimal. Sound familiar? :)
Use "rb":
FILE* file = fopen("C:/Path/to/file", "rb");
Change
FILE* file = fopen("C:/Path/to/file", "r");
to
FILE* file = fopen("C:/Path/to/file", "rb");
to read the file in binary mode. That usually helps to avoid such strange errors.

How to store the integer value "0" in a .bin file? (C++)

EDIT: Apparently, the problem is in the read function: I checked the data in a hex editer
02 00 00 00 01 00 00 00 00 00 00 00
So the zero is being stored as zero, just not read as zero.
Because when I use my normal store-in-bin file function:
int a = 0;
file.write(reinterpret_cast<char*>(&a), sizeof(a));
It stores 0 as the char version, or "\0", which obviously isn't stored (because it's a null value?) so when I call my function to read the zero value, it reads the value right after it (or right before if it would be the last in the file). So how can I store zero in a .bin file properly?
EDIT: Here are some of the functions relating to the read/write process:
//Init program: creates a sector.bin for another program to read from.
#include<fstream>
using namespace std;
int main()
{
fstream file;
file.open("sector.bin", ios::out | ios::binary);
if(!file.is_open())
{
file.open("sector.bin", ios::out | ios::binary);
file.close();
file.open("sector.bin", ios::out | ios::binary);
if(!file.is_open())
{
return -1;
}
}
file.seekp(file.beg);
int a = 2;
int b = 1;
int c = 0;
file.write(reinterpret_cast<char*>(&a), sizeof(a));
file.write(reinterpret_cast<char*>(&b), sizeof(b));
file.write(reinterpret_cast<char*>(&c), sizeof(c));
file.close();
return 0;
}
//Read function: part of another program that intializes variables based off
//of sector.bin
void sector::Init(std::fstream& file)
{
int top_i = FileRead(file,0);
std::cout<<top_i<<std::endl;
for(int i = 0; i < top_i; i++)
{
accessLV[i] = FileRead(file,i+1);
std::cout<<accessLV[i]<<std::endl;
}
std::cin.ignore();
viral_data.add(new X1(5,5,'X'));
viral_data.add(new X1(9,9,'X'));
player.set(0,0,'O');
return;
}
//the FileRead used in init
int FileRead(std::fstream& file, int pos)
{
int data;
file.seekg(file.beg + pos);
file.read(reinterpret_cast<char*>(&data), sizeof(data));
return data;
}
Also, the output for using sector::Init is as follows:
2
1
1
The ouput that I was trying to write into the bin was
2
1
0
So either the 0 is being read/written as a 1, or its not being written and Init is reading the last value twice.
int num = 0;
write( fd, &num, sizeof( int ));
It's not clear what do you mean by "storing integer value 0" in a file. Files contain bytes, not integers. Do you need to store sizeof(int) 0-bytes, or just one '\0' byte?
P.S. I also would guess the problem might be in your read code. Did you look at your .bin file in a hex editor?
P.P.S. Your problem is in seekg() function usage. Instead of passing the offset in bytes, you pass pos. It should be pos * sizeof(int) instead.
I'm not sure what you want to do, to me it seems the code you provided does what you're asking for:
int main() {
std::ofstream file("/tmp/tst.out");
int a = 0;
file.write(reinterpret_cast<char*>(&a), sizeof(a));
return 0;
}
This results in a file of four bytes size that contains the binary representation of a zero integer:
$ hexdump /tmp/tst.out
0000000 0000 0000
0000004
If you want to store the integer as it's ASCII representation you should use formatted stream output with <<:
std::ofstream file("/tmp/tst.out");
int a = 0;
file << a << std::endl;
This way you get:
$ cat /tmp/tst.out
0
You need to think what format the binary file should contain - something you don't have to do in the same way with text files, which is why many times a text file is used.
Assuming a (32-bit) machine where sizeof(int) == 4 (and CHAR_BITS == 8), then you can store 4 bytes that are all zero at the current file location using native format, then what you've got there should work, I think. You could experiment with other values such as 0x01020304, you will see the byte layout on your machine.
Of course, you need to be careful reading it back in, reversing the procedure used for writing. And don't forget to reposition the file before trying to re-read the data just written.