How to write a file byte by byte using c++?
unsigned short array[2]={ox20ac,0x20bc};
if i have a hexadecimal value 0x20ac how can i write it byte by byte in a file using c++
You can try something like this:
#include <fstream>
...
ofstream fout;
fout.open("file.bin", ios::binary | ios::out);
int a[4] = {100023, 23, 42, 13};
fout.write((char*) &a, sizeof(a));
fout.close();
One option, using standard C++ library:
#include <fstream>
#include <assert.h>
void main()
{
unsigned short array[2]={ox20ac,0x20bc};
std::ofstream file;
file.open("C:/1.dat", std::ios_base::binary);
assert(file.is_open());
for(int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
file.write((char*)(array + i * sizeof(array[0])), sizeof(array[0]));
file.close();
}
Alternatively, you can easily write your whole data in one go (without a loop):
file.write((const char*)array, sizeof(array));
To open an output file, use ofstream (output file stream, a subclass of ostream). Use the ios_base::binary mode (as second argument in the constructor or the open() member function) if you're not sure whether your output is human-readable text (ASCII).
To write a single byte, use the ostream member function "put". To write more than one byte at a time, use the ostream member function "write".
There are ways of taking data types (int, for example) longer than one byte and using them as arrays of bytes. This is sometimes called type-punning and is described in other answers, but beware of endianness and different sizes of data types (int can be 2-8 bytes), which can be different on different machines and compilers.
To test your output, reopen it as an input file and print the bytes.
ifstream in("myfile.txt", ios_base::binary);
while(!in.eof()) printf("%02X ", in.get()); //print next byte as a zero-padded width-2 capitalized hexadecimal).
in.close();
Or just use a hex editor like normal people.
you can use write function or ostream .
Use c++ function is ostream.
Related
I have a little problem, I want to write something like that 0xff to a file, and I have done it:
ofstream file;
file.open(this->dbFile, ios::app | ios::binary);
const char prefix = 0xff;
file.write(&prefix, sizeof(char));
The previous example works well, but this is not my issue.
I want to write the previous example with writing the hexadecimal literally like the following:
ofstream file;
file.open(this->dbFile, ios::app | ios::binary);
file.write((const char*)0xff, sizeof(char));
But unfortunately, there is a runtime error occurs with the second example.
I know there's something wrong with the data conversion, but what is it?
first char is often used as a synonym for the non existing type byte, however you could easily make your own using statement like
#include <cstdint>
using byte_t = int8_t;
Consider this line file.write((const char*)0xff, sizeof(char)); as ostream::Write(const byte_t* pointerToArrayOfData, std::streamsize sizeOfData). 0xFF is the data you want to write but not an address of an array holding your data. sizeof(char)=sizeof(byte_t)=1 can be neglected, the method is designed to write single bytes. However you can use this to serialize custom types like
struct Point { int8_t x, y; };
array<Point, 4> myRectangle {/* */};
file.write(&myRectangle, sizeof(Point) * array.size());
file.write(&myRectangle, sizeof(array<Point, 4>));
Note this is platform dependent and you should always consider the generated file can only be read on the same system you created it. If you want to transfer binary data please consider some abstractions like protobuf.
TLDR;
using byte_t = char;
void write_binary_data(std::ostream& ostream, byte_t* data, size_t count)
{
ostream.write(data, count);
}
using binary_data_t = std::vector<byte_t>;
void write_binary_data(std::ostream& ostream, const binary_data_t data)
{
write_binary_data(ostream, data.data(), data.size());
}
ofstream file;
file.open(this->dbFile, ios::app | ios::binary);
write_binary_data(file, { 0xFF, 0x00, 0xFF });
I'm having a little trouble figuring out how to write this value to a file correctly. I did a little research on the internet and found this article.
http://www.eecs.umich.edu/courses/eecs380/HANDOUTS/cppBinaryFileIO-2.html
#include <fstream>
#include <iostream>
int main()
{
int testVar = 71;
std::ofstream outputFile;
outputFile.open("C:/binary.dat", std::ios::out | std::ios::binary);
outputFile.seekg(0);
outputFile.write(&testVar, sizeof(testVar));
outputFile.close();
}
What I understand from the article is that the first parameter is a void pointer? which means that it will accept any type? But when I'm typing it out, the intelisense says there is no overload and the first parameter takes type char*.
Am I using the wrong header or something from an older C++ version??
Could really use some help here.
Thanks!
I am not familiar with the history of development of the functions. Hence, I can't comment on why the arguments are of type char* and not void*.
To solve your problem...
You can use:
outputFile.write(reinterpret_cast<char*>(&testVar), sizeof(testVar));
Use reinterpret_cast while using istream::read() also.
You really just need to cast it to char* like was said before, but there are other problems with the code.
seekg() is for input streams, and you are writing an output file. If you meant to clear the line, just open the file with trunc.
#include <fstream>
#include <iostream>
int main()
{
int testVar = 71;
std::ofstream outputFile("C:/binary.dat", std::ios::out | std::ios::binary | std::ios::trunc);
outputFile.write((char*)&testVar, sizeof(testVar));
outputFile.close();
}
The first parameter is a char*.
char having size 1 byte signifies byte by byte data and char* signifies a block of data.
Hence when writing raw binary data, the data is passed as a char* and size of the block.
Am I using the wrong header or something from an older C++ version??
No it is not the problem as stated it is char* and not void* that is taken as argument.
NOTE The seekg() member function is for input streams. I think the functionality you needed was seekp()
and thank you in advance for your help!
I am in the process of learning C++. My first project is to write a parser for a binary-file format we use at my lab. I was able to get a parser working fairly easily in Matlab using "fread", and it looks like that may work for what I am trying to do in C++. But from what I've read, it seems that using an ifstream is the recommended way.
My question is two-fold. First, what, exactly, are the advantages of using ifstream over fread?
Second, how can I use ifstream to solve my problem? Here's what I'm trying to do. I have a binary file containing a structured set of ints, floats, and 64-bit ints. There are 8 data fields all told, and I'd like to read each into its own array.
The structure of the data is as follows, in repeated 288-byte blocks:
Bytes 0-3: int
Bytes 4-7: int
Bytes 8-11: float
Bytes 12-15: float
Bytes 16-19: float
Bytes 20-23: float
Bytes 24-31: int64
Bytes 32-287: 64x float
I am able to read the file into memory as a char * array, with the fstream read command:
char * buffer;
ifstream datafile (filename,ios::in|ios::binary|ios::ate);
datafile.read (buffer, filesize); // Filesize in bytes
So, from what I understand, I now have a pointer to an array called "buffer". If I were to call buffer[0], I should get a 1-byte memory address, right? (Instead, I'm getting a seg fault.)
What I now need to do really ought to be very simple. After executing the above ifstream code, I should have a fairly long buffer populated with a number of 1's and 0's. I just want to be able to read this stuff from memory, 32-bits at a time, casting as integers or floats depending on which 4-byte block I'm currently working on.
For example, if the binary file contained N 288-byte blocks of data, each array I extract should have N members each. (With the exception of the last array, which will have 64N members.)
Since I have the binary data in memory, I basically just want to read from buffer, one 32-bit number at a time, and place the resulting value in the appropriate array.
Lastly - can I access multiple array positions at a time, a la Matlab? (e.g. array(3:5) -> [1,2,1] for array = [3,4,1,2,1])
Firstly, the advantage of using iostreams, and in particular file streams, relates to resource management. Automatic file stream variables will be closed and cleaned up when they go out of scope, rather than having to manually clean them up with fclose. This is important if other code in the same scope can throw exceptions.
Secondly, one possible way to address this type of problem is to simply define the stream insertion and extraction operators in an appropriate manner. In this case, because you have a composite type, you need to help the compiler by telling it not to add padding bytes inside the type. The following code should work on gcc and microsoft compilers.
#pragma pack(1)
struct MyData
{
int i0;
int i1;
float f0;
float f1;
float f2;
float f3;
uint64_t ui0;
float f4[64];
};
#pragma pop(1)
std::istream& operator>>( std::istream& is, MyData& data ) {
is.read( reinterpret_cast<char*>(&data), sizeof(data) );
return is;
}
std::ostream& operator<<( std::ostream& os, const MyData& data ) {
os.write( reinterpret_cast<const char*>(&data), sizeof(data) );
return os;
}
char * buffer;
ifstream datafile (filename,ios::in|ios::binary|ios::ate);
datafile.read (buffer, filesize); // Filesize in bytes
you need to allocate a buffer first before you read into it:
buffer = new filesize[filesize];
datafile.read (buffer, filesize);
as to the advantages of ifstream, well it is a matter of abstraction. You can abstract the contents of your file in a more convenient way. You then do not have to work with buffers but instead can create the structure using classes and then hide the details about how it is stored in the file by overloading the << operator for instance.
You might perhaps look for serialization libraries for C++. Perhaps s11n might be useful.
This question shows how you can convert data from a buffer to a certain type. In general, you should prefer using a std::vector<char> as your buffer. This would then look like this:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::ifstream input("your_file.dat");
std::vector<char> buffer;
std::copy(std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>(),
std::back_inserter(buffer));
}
This code will read the entire file into your buffer. The next thing you'd want to do is to write your data into valarrays (for the selection you want). valarray is constant in size, so you have to be able to calculate the required size of your array up-front. This should do it for your format:
std::valarray array1(buffer.size()/288); // each entry takes up 288 bytes
Then you'd use a normal for-loop to insert the elements into your arrays:
for(int i = 0; i < buffer.size()/288; i++) {
array1[i] = *(reinterpret_cast<int *>(buffer[i*288])); // first position
array2[i] = *(reinterpret_cast<int *>(buffer[i*288]+4)); // second position
}
Note that on a 64-bit system this is unlikely to work as you expect, because an integer would take up 8 bytes there. This question explains a bit about C++ and sizes of types.
The selection you describe there can be achieved using valarray.
I have the following code and i am trying to write some data in a binary file.
The problem is that i don't have any experience with binary files and i cant understand what i am doing.
#include <iostream>
#include <fstream>
#include <string>
#define RPF 5
using namespace std;
int write_header(int h_len, ofstream& f)
{
int h;
for(h=0;h<h_len;h++)
{
int num = 0;
f.write((char*)&num,sizeof(char));
}
return 0;
}
int new_file(const char* name)
{
ofstream n_file(name,ofstream::binary);
write_header(RPF,n_file);
n_file.close();
return 0;
}
int main(int argc, char **argv)
{
ofstream file("file.dat",ofstream::binary);
file.seekp(10);
file.write("this is a message",3);
new_file("file1.dat");
cin.get();
return 0;
}
1. As you can see i am opening file.dat and writing inside the word "thi". Then i open the file and i see the ASCII value of it. Why does this happen?
Then i make a new file file1.dat and i try to write in it the number 0 five times.
What i am supposed to use?
this
f.write((char*)&num,sizeof(char));
or this
f.write((char*)&num,sizeof(int));
and why i cant write the value of the number as is and i have to cast it as a char*?
Is this because write() works like this or i am able to write only chars to a binary file?
Can anyone help me understand what's happening?
Function write() that a pointer to your data buffer and the length in bytes of the data to be streamed to the file. So when you say
file.write("this is a message",3);
you tell the write function to write 3 bytes in the file. And that is "thi".
This
f.write((char*)&num,sizeof(char));
tells the write function to put sizeof(char) bytes in the file. That is 1 byte. You probably want it
f.write((char*)&num,sizeof(int));
as num is a int variable.
You are writing the ASCII string "thi" to file.dat. If you opened the file in a hex editor, you would see "74 68 69", which is the numeric representations of those characters. But if you open file.dat in an editor that understands ASCII, it will most likely translate those values back to their ASCII representation to make it easier to view. Opening the ofstream in ios::binary mode means that data is output to file as is, and no transformations may be applied by the stream before hand.
The function ofstream::write(const char *data, streamsize len) has two parameters. data is like this so that write is operating on individual bytes. That is why you have to cast num to a char* first. The second parameter, len, indicates how many bytes, starting from data that will be written to the file. My advise would be to use write(static_cast<char*>(num), sizeof(num)), then set num to be a type big enough to store the data required. If you declare int num, then on a 32bit platform, 20 zero bytes would be written to the file. If you only want 5 zero bytes, then declare as char num.
I've got a struct with 2 integers, and I want to store them in a binary file and read it again.
Here is my code:
static const char *ADMIN_FILE = "admin.bin";
struct pw {
int a;
int b;
};
void main(){
pw* p = new pw();
pw* q = new pw();
std::ofstream fout(ADMIN_FILE, ios_base::out | ios_base::binary | ios_base::trunc);
std::ifstream fin(ADMIN_FILE, ios_base::in | ios_base::binary);
p->a=123;
p->b=321;
fout.write((const char*)p, sizeof(pw));
fin.read((char*)q, sizeof(pw));
fin.close();
cout << q->a << endl;
}
The output I get is 0. Can anyone tell me what is the problem?
You probably want to flush fout before you read from it.
To flush the stream, do the following:
fout.flush();
The reason for this is that fstreams generally want to buffer the output as long as possible to reduce cost. To force the buffer to be emptied, you call flush on the stream.
When storing integers to files, you can use the htonl(), ntohl() family of functions to ensure that they will be read back in the correct format regardless of whether the file is written out on a big-endian machine, and read back later on a small-endian machine. The functions were intended for network use, but can be valuable when writing to files.
fin.write((char*)q, sizeof(pw));
Should probably be
fin.read((char*)q, sizeof(pw));
Be warned that your method assumes things about the size and endianness of your integers and the packing of your structures, none of which is necessarily going to be true if your code gets ported to another machine.
For portability reasons, you want to have output routines that output the fields of structures separately, and that output numbers at specific bitwidths with specific endianness. This is why there are serialization packages.
try this:
fout.write((const char*)&p, sizeof(pw));
fin.read((char*)&q, sizeof(pw));
instead of
fout.write((const char*)p, sizeof(pw));
fin.read((char*)q, sizeof(pw));
vagothcpp (yournotsosmartc++programmer=p)