1

I am trying to write an int array to a fstream, but I am getting an exception when I call fstream.write.

Can I use fstream to write an int array to a file?

int main(int argc, char * argv[])
{
    fstream amostra("D:\\Amostra.txt", ios::out | ios::binary);
    const int total_elements_block = 1024;
    const int buffer_size  = total_elements_block;

    const int total_buffer = 10;

    int * buffer = new int [buffer_size];
    //for (int j=0; j<total_buffer; j++){
        for (int i =0; i<total_elements_block; i++){
            buffer[i] = i;
        }
        amostra.write((char *)(&buffer), total_elements_block*4);
    //}

    amostra.close();
    delete []buffer;

    return 0;
}
Jay Sullivan
  • 17,332
  • 11
  • 62
  • 86
p.magalhaes
  • 7,595
  • 10
  • 53
  • 108
  • 1
    "Can i use fstream to write a int buffer in a file?" fstream can write whatever you want to file if you format it properly. Simple answer: yes. If you want _actual code_ then request that and not a simple boolean answer. – TheZ Jun 22 '12 at 15:58
  • 1
    Please post the exception you getting. – Jay Sullivan Jun 22 '12 at 16:00
  • You should probably use total_elements_block*sizeof(buffer[0]), just to be safe/portable :-) – Robert Mason Jun 22 '12 at 16:12
  • This isn't Java. If you want to create a local array, then just create the array locally. `int buffer [buffer_size];`. Avoid `new` whenever possible. If you ever see `delete` in your own code in C++, you are doing something wrong. `new` should almost never be used, and when it is, it should be used with a smart pointer (that takes care of the `delete` for you). – David Stone Jun 22 '12 at 16:16
  • @RobertMason Look again. That would cause him to output 4096 int's instead of 4096 bytes as you are probably thinking. – Captain Obvlious Jun 22 '12 at 16:18
  • @CaptainOblivious: I was talking about the call to write, which already has a *4. – Robert Mason Jun 22 '12 at 16:22
  • @DavidStone Spoke as someone who never had to interoperate with C libraries, nor write high-performance low level code... – lvella Jun 22 '12 at 16:29
  • @lvella My advice is to avoid the free store ("the heap") wherever possible. Using `new` for data that is entirely local in its lifetime will only lead to memory fragmentation and reduce locality of reference (in addition to potentially adding memory leaks). There are few things worse than scattering your data throughout memory if you care about performance. – David Stone Jun 23 '12 at 00:11
  • @lvella This is why I'd rather delete a particular value from the middle of a `std::vector` than a `std::list`, for performance reasons. The `std::vector` is laid out sequentially in memory; the `std::list` is not. Simply iterating over a `std::list` is so much slower that it dwarfs the cost of shifting every single element in a `std::vector`. When it comes to performance, data locality is king. – David Stone Jun 23 '12 at 00:12
  • @lvella In cases where you need dynamic memory management, using the appropriate smart pointer will not cost you anything compared to managing memory yourself, but will get you a large increase in readability and safety. I feel it goes without saying that if you call a library function that allocates memory, you'll have to manually free it. However, I would immediately put the pointer returned by the library function into some sort of class that cleans up in the destructor, so most of my code is still not calling `delete` (just that one place, and only as the lesser of two evils). – David Stone Jun 23 '12 at 00:12
  • For these reasons, I reject your implication that I am unaware of performance concerns in writing code. I simply do not let the C way of writing things get in the way of writing faster, easier to read code. Although to be honest, calling `new` and then calling `delete` to simulate an automatic variable is really closer to the Java way of putting everything on the heap than it is to the C way. – David Stone Jun 23 '12 at 00:14

2 Answers2

5

You aren't passing the address to the buffer correctly.

(char *)(&buffer)

tells the compiler to take the address of buffer instead of using the pointer contained in buffer which of points to the memory allocated with new. To get the address of the buffer itself change it to the following.

(char *)(buffer)
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
5

Captain Obvlious is correct in diagnosing your problem, however, there are really a few possible fixes here.

You can do as he suggests and use (char *)(buffer), but I disagree with this stylistically.

First off, it uses a C-style cast, which should be avoided in C++ code. That would make a slightly improved version be reinterpret_cast<char *>(buffer). This will ensure you don't do anything silly like remove const.

However, I feel that you can do slightly better than that. At some point, you may decide that a plain array will not work for you. Maybe you want to change to a C++11 std::array, or a std::vector. Suddenly your code won't work. A plain C-style array is the data type I change most often. For this reason, you may want to consider something that looks more like reinterpret_cast<char *>(& buffer[0]).

Also note that your code is not portable. The way that an int is laid out in memory is implementation defined. Look at answers such as Detecting endianness programmatically in a C++ program

Community
  • 1
  • 1
David Stone
  • 26,872
  • 14
  • 68
  • 84