Save to file with vector (dynamically)

I have created a programme that does calculations and generates results from those calculations.

The imformation generated is stored in variables for later display. Everything works well when it is displayed to screen and when sent to a file for saving.

Part of the information required is generated dynamically from a vector. The reason is that the number of items vary depending on the requirements to be calculated. As a result I don't have a way of storing other that the vector. There is no difficulty with the display to screen but it does not go to the file because the information is no longer available.

I created a copy of the display function dedicated to saving to file.

When I try to save the information to file with the new function, the file is created but is empty when I include the following code (which is the same as in the original function to screen) :

1
2
3
4
5
6
7
8
 int i =0;
 int count = 1;
          
 for( i = 0; i < fileOut.size()-1; i++)
 {                
     cout << "("	 << count <<  ") = " << fileOut[i] << "    feet" << endl; 
     count = count + 1;				
 }


Please note: fileOut is the vector.

I would be grateful if anyone could assist in finding a solution.
> When I try to save the information to file with the new function, the file is created but is empty
> when I include the following code (which is the same as in the original function to screen) :

You're still outputting to the screen.

Replace the cout with your opened file object.
information that does not change should be avoided if possible. For example, if you have 50,000 lines of text that all look like (x) feet, then you need to know if the file is meant to be read by humans or imported into something like excel where this information is useful. If the only thing that ever reads your file will be your own program, then you can save the 6 bytes per line which is a lot of space... and not just the wasted space, but now your reader needs to either parse the data and do something with it or discard it, extra logic...
Last edited on
I do not know (nor really care) what C++ standard you are building your source to or your compiler....

C++17 added the <filesystem> library that can make dealing with files much easier.

C++20 added the <format> library, making it easier to format data to be displayed to the console/written to a file.

When opening files it is best to check the file actually opened before reading/writing data. Trying to read data from a file that didn't properly open is gonna cause problems.

There are newer and safer ways to do for loops that reduce the possibility of accessing your container's elements going out of bounds.

While this particular problem is easily identifiable, sending your output to the console instead of a file, giving us a self-contained and compilable example makes it easier for us to help you.

The following example doesn't use <filesystem>, requires C++20 or later:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <fstream>
#include <iostream>
#include <vector>
#include <format>

int main( )
{
   std::vector v { 1.2, 2.3, 4.5, 5.6, 7.8, 9.0 };

   std::ofstream myFile;
   myFile.open( "DataFile.txt", std::ios_base::out );

   if ( myFile.is_open( ) )
   {
      std::cout << "File open successful\n";

      for ( size_t count { }; const auto&  itr: v )
      {
         // duplicate the output to the console and the file to see what it looks like.
         // easier to format the output that way.  Remove the std::cout when
         // no longer needed.
         std::cout << std::format( "({:>10} ) {:.3f} feet\n", count, itr );
         myFile << std::format( "({:>10} ) {:.3f} feet\n", count, itr );
         count++;
      }
      std::cout << '\n';

      std::cout << "Finished writing to file, will close now\n";
      myFile.close( );
   }
   else { std::cerr << "Unable to open file, exiting!\n"; }
}

File open successful
(         0 ) 1.200 feet
(         1 ) 2.300 feet
(         2 ) 4.500 feet
(         3 ) 5.600 feet
(         4 ) 7.800 feet
(         5 ) 9.000 feet

Finished writing to file, will close now


An example using <filesystem>, creating a sub-directory and a file for output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <filesystem>
#include <fstream>
#include <iostream>

// for simplicity
using namespace std::filesystem;

int main( )
{
   // Define the path to create directory
   path directorypath = "mydirectory";

   // To check if the directory exist or not, create it if
   // doesn't exist
   if ( !exists( directorypath ) )
   {
      create_directory( directorypath );
      std::cout << "Directory created: " << directorypath << '\n';
   }

   // Define the file path within the directory and
   // combining the directory
   path filepath = directorypath / "myFile.txt";

   // Create and open the file for writing using
   // std::ofstream
   std::ofstream file( filepath );
   if ( file.is_open( ) )
   {
      // Write data to the file
      file << "Hello, FileSystem!";
      file.close( );
      std::cout << "File created: " << filepath << '\n';
   }
   else
   {
      // Handle the case if any error occurred
      std::cerr << "Failed to create file: " << filepath << '\n';
   }
}

Checking the open status of a file for reading is super-critical.
Pleasee accept my sincerest appology for my delayed response. Here is the save function that I have been using. As I indicated before, it works very well except when the vector code is included.(I am using C++ 11)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void saveFile(ostream& strm)   
{
    string my_string;
    string filename;
    filename = "string";
    char txt;
    cout << "\n";
    cout << "Enter file name: ";
    cin >> my_string;
    cout << "\n";
    filename = my_string+'.'+"txt";
    ofstream file(filename.c_str());
  
    cout << "File " << filename << " is opened \n\n";
    
    if(!file)
    {
   	    cout << "Cannot open " <<filename<< " file. \n ";
	    return; 
    }   
       
    auto del = [&](streambuf* p){strm.rdbuf(p);};
    unique_ptr<streambuf, decltype(del)> origBuffer(strm.rdbuf(), del);   
	 
    strm.rdbuf(file.rdbuf());
     
    if(file.is_open())
    {
    	cout << "This works\n";
    	
        printOut();
		              
    } 	   
       
    if(filename.size() == 0)
    {   
        cout << "\nFile " <<filename << " is empty \n";
        return ; 
    }
   
    file.clear();
   
    file.close();  
    
 system("pause");
 return;	
}


I have not beenable to make progress from the suggestions provided.
> auto del = [&](streambuf* p){strm.rdbuf(p);};
> unique_ptr<streambuf, decltype(del)> origBuffer(strm.rdbuf(), del);
I would suggest stop trying to be overly clever with low level buffer hackery and do the job in the obvious simple way.

A vector is a composite object. You can't just write it all out as a blob and hope to read it all back in again later as a blob.


A vector is a composite object. You can't just write it all out as a blob and hope to read it all back in again later as a blob.


yes, 'but' ... if you were doing a binary file it can absolutely be treated as a blob. The internal data is ensured to be stored like a C array, in one solid blob of bytes, and you can chuck that to the disk or network and rebuild it on the other side. You only need 1 extra piece of data... the number of records you wrote out ... and you can make a new vector from the blob. Gets ugly if the vector's type isn't friendly to direct writing, but you would have designed it not to be if doing this kind of read/write.

"text" files, ... exactly what you said. I wonder if the OP saw code online for a binary file and did not realize...

baby steps. just loop over the vector and write each record to the file as you would for cout. Get that working. You can get weird with it later once you understand that simple approach.
Last edited on
Coubarrie wrote:
1
2
3
4
5
6
7
int i = 0;
int count = 1;
for( i = 0; i < fileOut.size()-1; i++)
{                
  // Do something with fileOut[i]
  count = count + 1;				
}

Unrelated to the writing:
* Why is the counter i declared outside of the loop?
* What is the purpose of the count variable?
* Why the last element of the vector is not used?
Registered users can post here. Sign in or register to post.