tags:

views:

254

answers:

6

I would like to know how to output an array of doubles to the hard drive.

edit:

for further clarification. I would like to output it to a file on the hard drive (I/O functions). Preferably in a file format that can be quickly translated back into an array of doubles in another program. It would also be nice if it was stored in a standard 4 byte configuration so that i can look at it through a hex viewer and see the actual values.

+1  A: 
#include <fstream.h>

void saveArray(double* array, int length);

int main()
{
    double array[] = { 15.25, 15.2516, 84.168, 84356};
    saveArray(array, 4);

    return 0;
}

void saveArray(double* array, int length)
{
    ofstream output("output.txt");

    for(int i=0;i<length;i++)
    {
        output<<array[i]<<endl;
    }
}

here is a way to output an array of doubles to text file one per line. hope this helps
EDIT
Change top one line to this two, and it will compile in VS. You can use multithreading to not blocking system wile saving data

#include <fstream>

using namespace std;
ArsenMkrt
Hmm, thanks for your response. It doesn't seem to compile on my VC++ for some reason. Even though it doesn't compile, there still is the problem of using the loop to output everything. In my experience its much slower than using .write() . Since I'm outputting millions of doubles, it would be very very slow, i need something that is fast and efficient!
Faken
see edited post, for compiling in VS
ArsenMkrt
A: 
#include <iostream>
#include <fstream>

using namespace std;

int main () {
  double [] theArray=...;
  int arrayLength=...;
  ofstream myfile;
  myfile.open ("example.txt");
  for(int i=0; i<arrayLength; i++) {
    myfile << "theArray[i]\n";
  }
  myfile.close();
  return 0;
}

adapted from http://www.cplusplus.com/doc/tutorial/files/

Just set theArray and arrayLength to whatever your code requires.

Jeremybub
Do you mean myfile << theArray[i] << "\n"; ? Otherwise you'll just repeatedly be printing the literal "theArray[i]".
Dominic Rodger
Is there any other method other than outputting each element individually? It's much too slow for my application. Is there some way to say to the computer: "hey! Take the stuff the double array is stored on in RAM and just dump it into a file and slap a .txt on the end of it" ?
Faken
If writing each element is too slow, why not just construct a string of all the entries and write that one string to disk?
Soo Wei Tan
Disk caching makes writing every one individually just as fast as writing it all at once.
Jeremybub
+3  A: 

You can use iostream .read() and .write().

It works (very roughly!) like this:

double d[2048];
fill(d, d+2048, 0);
ofstream outfile ("save.bin", ios::binary);
outfile.write(reinterpret_cast<char*>(&d), sizeof(d));

ifstream infile ("save.bin", ios::binary);
infile.read(reinterpret_cast<char*>(&d), sizeof(d));

Note that this is not portable between CPU architectures. Some may have different sizes of double. Some may store the bytes in a different order. It shouldn't be used for data files that move between machines or data that is sent over the network.

Zan Lynx
I would bold the whole first sentence of your disclaimer.
Martin York
I know this is being picky, but file should be *.txt if you are saving as binary.
Zack
meant to say _shouldn't_ be *.txt
Zack
I implemented this and I ended up getting strange errors all over the place, actually random strange errors that sometimes happen, and sometimes don't...even between two separate, yet identical runs of the program.
Faken
You have to set the array to something before you use it. The code sample is not something you can use as-is, it is just an example.
Zan Lynx
No I realize that, and I did exactly that except it kept giving me access violations randomly...to be honest, I wouldn't even know where to begin explaining my problem other than every few runs or so, i would run into an access violation. Something which I know my code did not produce...i spent 3 hours looking at thousands of variables and finding nothing wrong...except that one error i made, which even after corrected, the program would still give me access violations until i removed the writing bit of code and replaced it with the code in the picked answer.
Faken
It could be the sizeof(d) thing. That only works if the array is in scope. If used on a pointer it returns the size of the pointer. 4 bytes usually. In that case you need length*sizeof(double) instead of sizeof(d)
Zan Lynx
+1  A: 

Hey... so you want to do it in a single write/read, well its not too hard, the following code should work fine, maybe need some extra error checking but the trial case was successful:

#include <string>
#include <fstream>
#include <iostream>

bool saveArray( const double* pdata, size_t length, const std::string& file_path )
{
    std::ofstream os(file_path.c_str(), std::ios::binary | std::ios::out);
    if ( !os.is_open() )
     return false;
    os.write(reinterpret_cast<const char*>(pdata), std::streamsize(length*sizeof(double)));
    os.close();
    return true;
}

bool loadArray( double* pdata, size_t length, const std::string& file_path)
{
    std::ifstream is(file_path.c_str(), std::ios::binary | std::ios::in);
    if ( !is.is_open() )
     return false;
    is.read(reinterpret_cast<char*>(pdata), std::streamsize(length*sizeof(double)));
    is.close();
    return true;
}

int main()
{
    double* pDbl = new double[1000];
    int i;
    for (i=0 ; i<1000 ; i++)
     pDbl[i] = double(rand());

    saveArray(pDbl,1000,"test.txt");

    double* pDblFromFile = new double[1000];
    loadArray(pDblFromFile, 1000, "test.txt");

    for (i=0 ; i<1000 ; i++)
    {
     if ( pDbl[i] != pDblFromFile[i] )
     {
      std::cout << "error, loaded data not the same!\n";
      break;
     }
    }
    if ( i==1000 )
     std::cout << "success!\n";

    delete [] pDbl;
    delete [] pDblFromFile;

    return 0;
}

Just make sure you allocate appropriate buffers! But thats a whole nother topic.

DeusAduro
Strange why this one didn't get voted more, it is actually much better in terms of portability.Thanks a bunch, it worked great and I learned a few things!
Faken
Not sure why you'd rate this one better for portability. It uses the same binary read/write as my answer and all the portability problems still exist. This one *is* a more complete answer, being a whole program and not just a code snip.
Zan Lynx
+1  A: 

Use std::copy() with the stream iterators. This way if you change 'data' into another type the alterations to code would be trivial.

#include <algorithm>
#include <iterator>
#include <fstream>

int main()
{
    double         data[1000] = {/*Init Array */};

    {
        // Write data too a file.
        std::ofstream   outfile("data");
        std::copy(data,
                  data+1000,
                  std::ostream_iterator<double>(outfile," ")
                 );
    }

    {
        // Read data from a file
        std::ifstream    infile("data");
        std::copy(std::istream_iterator<double>(infile),
                  std::istream_iterator<double>(),
                  data // Assuming data is large enough.
                 );
    }
}
Martin York
I like this style but its even better if you use a vector<double> instead of an array and back_inserter(data) instead of data in the copy from ifstream.
Zan Lynx
Or a list or a set or just about anything else. They all work with only minor change.
Martin York
A: 

Now I feel old. I asked this question a long time ago (except about ints). comp.lang.c++ link

Zack