2

I need to write C++ code that will open a binary file and will write 5 MB of '1' in to it.

Currently my code is:

#define BYTES_BUFFER_SIZE_5MB (1024*1024*5)

static char buffer[BYTES_BUFFER_SIZE_5MB];
memset(buffer, 0xff, BYTES_BUFFER_SIZE_5MB);
ofstream myFile ("data.bin", ios::out | ios::binary);
myFile.write(buffer, BYTES_BUFFER_SIZE_5MB);

Is there a memset-like method for writing to a file, so I can avoid having a buffer?

AndyG
  • 39,700
  • 8
  • 109
  • 143
talw
  • 61
  • 2
  • 2
    `1024*1024*5` = merry hell if you have a 16 bit `int`. You have to be very careful with compile time evaluable constant expressions. – Bathsheba Nov 15 '17 at 15:46
  • A nice feature of using a large buffer is that the system can process the data transfer in the background. For example, the driver could use a DMA processor to transfer the data to the hard drive. The relieves the CPU of having to read memory, write data to the device, repeat. – Thomas Matthews Nov 15 '17 at 17:19
  • There is an overhead to each transaction. The optimal solution is to maximize data sizes per transaction. The overhead could be: drive spinning up, drive spinning down, locating sectors, etc. – Thomas Matthews Nov 15 '17 at 17:21

3 Answers3

2

I think we can do this in one line with stream manipulators:

fout << std::setw(BYTES_BUFFER_SIZE_5MB - 1) << std::setfill(char(0xFF)) << char(0xFF);
  • setw to set the number of bytes to write out
  • setfill to make it write out 0xFF by default

That way we don't have a buffer involved. The only risk is if you want to write a lot of bytes, you risk overflowing int on your call to setw.

AndyG
  • 39,700
  • 8
  • 109
  • 143
  • It should be noted that you can use a compile time value for the size sent to setw, making this useful for padding out binary structures when writing them to files. – TheBat Dec 12 '18 at 21:27
0

You can use a smaller buffer and write it several times with a for loop.

If you have to write 5Mb you can do something like

#define BYTES_SIZE_5MB (5242880) // Bathsheba comment have to be considered
#define BUFFER_SIZE (1024) // Chunk size to be written (this is an arbitrary amount)

static char buffer[BUFFER_SIZE];
ofstream myFile ("data.bin", ios::out | ios::binary);
int i, repetitions = BYTES_SIZE_5MB / BUFFER_SIZE;
memset(buffer, 0xff, BUFFER_SIZE);
for (i=0; i < repetitions; ++i)
    myFile.write(buffer, BYTES_BUFFER_SIZE_5MB);
myFile.close();

Note write() method could become really slow, it's better to choose a bigger chunk size and that way you will do less write calls, which improves the speed of your program

alseether
  • 1,889
  • 2
  • 24
  • 39
0

It's not simpler, but you can use memory-mapped files. They give you exactly what you asked for - you can write the file as if you're writing to memory.

Each (popular) operating system have different API for them, but there are a few libraries that provide portable support.

Itaypk
  • 1,103
  • 10
  • 25