How do I save/load information onto/from my device? - c++

I'm developing an application, but I need it to save its information onto the computer, and load it from there next time it's opened.
To give the simplest example: I have an array of strings and I want to save them as a *.txt file in the application's directory. And every member of the array should be on a new row of the file.
And I want to load the entries of the file into the array when I open the app, or create an empty *.txt file, if one doesn't exist.
Note: if there is an easier way to do this, instead of saving them into a *.txt, please tell me. Saving them strictly as a *.txt format isn't mandatory.
Also, I am using wxWidgets for my application, if it's gonna make it any easier.

MainFrame::MainFrame() {
wxFileName f(wxStandardPaths::Get().GetExecutablePath());
wxString appPath(f.GetPath());
std::ifstream inputFileStream;
inputFileStream.open(std::string(appPath.mb_str(wxConvUTF8)) + "data.txt");
std::string data;
inputFileStream >> data;
}
MainFrame::~MainFrame()
{
wxFileName f(wxStandardPaths::Get().GetExecutablePath());
wxString appPath(f.GetPath());
std::ofstream outputFileStream;
outputFileStream.open(std::string(appPath.mb_str(wxConvUTF8)) + "data.txt");
std::string data = "something";
outputFileStream << data;
outputFileStream.close();
}
When frame is created, I get the data. When frame is destroyed, I save the data. I don't use C++ standard library classes, but wxWidgets classes and methods for UTF-8 support. (I haven't checked if this piece of code works – it's taken from my old project.)

Related

How to writte a file in c++, considering that everytime you run the code, the file keeps storing the previous data?

I'm working in creating a file that contains the data that describes the position of a cell in fuction of time. I was adviced to use snprintf. These were the lines of code that I used to introduce the function:
int n_sample = 50;
char filename[101];
snprintf(filename, sizeof(filename),"dados_movimento_celula_%d.dat", n_sample);
The code runs, showing no errors, however, it keeps alterating the file by replacing the previous data with the new one, instead of just adding the new one set of data. How to fix this?
You can use ofstream and open the file in append mode:
std::ofstream outFile;
outfile.open(fileName, std::ios_base::app);
outFile << content;

Pass Binary string/file content from c++ to node js

I'm trying to pass the content of a binary file from c++ to node using the node-gyp library. I have a process that creates a binary file using the .fit format and I need to pass the content of the file to js to process it. So, my first aproach was to extract the content of the file in a string and try to pass it to node like this.
char c;
std::string content="";
while (file.get(c)){
content+=c;
}
I'm using the following code to pass it to Node
v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(args.GetIsolate(), (void*)content.data(), content.size());
args.GetReturnValue().Set(ab);
In node a get an arrayBuffer but when I print the content to a file it is different to the one that show a c++ cout.
How can I pass the binary data succesfully?
Thanks.
Probably the best approach is to write your data to a binary disk file. Write to disk in C++; read from disk in NodeJS.
Very importantly, make sure you specify BINARY MODE.
For example:
myFile.open ("data2.bin", ios::out | ios::binary);
Do not use "strings" (at least not unless you want to uuencode). Use buffers. Here is a good example:
How to read binary files byte by byte in Node.js
var fs = require('fs');
fs.open('file.txt', 'r', function(status, fd) {
if (status) {
console.log(status.message);
return;
}
var buffer = new Buffer(100);
fs.read(fd, buffer, 0, 100, 0, function(err, num) {
...
});
});
You might also find these links helpful:
https://nodejs.org/api/buffer.html
<= Has good examples for specific Node APIs
http://blog.paracode.com/2013/04/24/parsing-binary-data-with-node-dot-js/
<= Good discussion of some of the issues you might face, including "endianness" and "interpreting numbers"
ADDENDUM:
The OP clarified that he's considering using C++ as a NodeJS Add-On (not a standalone C++ program.
Consequently, using buffers is definitely an option. Here is a good tutorial:
https://community.risingstack.com/using-buffers-node-js-c-plus-plus/
If you choose to go this route, I would DEFINITELY download the example code and play with it first, before implementing buffers in your own application.
It depends but for example using redis
Values can be strings (including binary data) of every kind, for
instance you can store a jpeg image inside a value. A value can't be
bigger than 512 MB.
If the file is bigger than 512MB, then you can store it in chunks.
But I wouldnt suggest since this is an in-memory data store
Its easy to implement in both c++ and node.js

How do I use QuaZip to extract multiple files?

I have the below code to move through a list of the folders and files in a zip archive creating them as I goes (also creating paths for files if not created yet).
The application crashes when I use readData(char*, qint64) to extract internal files data to stream it into a QFile. I don't think this is the right thing to use but it's all I've seen (in a very loose example on this site) and I also had to change the QuaZipFile.h to make the function public so I can use it (also hinting I shouldn't be using it).
It doesn't crash on the first file which has no contents but does after that. Here is the necessary code (ask if you need to see more):
QFile newFile(fNames);
newFile.open(QIODevice::WriteOnly);
QTextStream outToFile(&newFile);
char * data;
int len = file.readData(data, 100000000);
if(len > 0) {
outToFile << data;
}
newFile.close();
It doesn't pass the int len line. What should I be using here?
Note that the variable file is defined earlier pretty puch like this:
QuaZip zip("zip.zip");
QuaZipFile file(&zip);
...
zip.goToFirstFile();
...
zip.goToNextFile();
And the int passed to readData is a random number for the max data size.
The reason for the crash is that you have not allocated any memory for your buffer, named data.
Solved.
I tried using different reads (readData, read, readLine) and found that this line works with no need for a data buffer:
outToFile << file.readAll();

Force read on disk with std::ifstream instead of the file cache

I have a program that load data from a file using std::ifstream and store the data in a structure. After that, I verify if the data I want was in the file. If it is not, I ask the user to modify the file and press a key. I then reload the file. The problem is that even if the user modified the file, I always get the same data in the file because the file seems to be cache in the application. I've seen that in win32 API, it's possible to use the flag FILE_FLAG_NO_BUFFERING to avoid using a buffered copy when reading a file, but I would like to use that feature with std::ifstream. Is there any way to use the handle created through win32 api with ifstream or anyway to force it directly in std::ifstream ?
Here's a "simplified" code sample:
SomeStructure s = LoadData(fileName);
while(!DataValid(s))
s = LoadData(fileName);
SomeStructure LoadData(const std::string& fileName)
{
std::ifstream fileStream;
while(!OpenFileRead(fileName, fileStream))
{
std::cout<<"File not found, please update it";
fileStream.close();
//Wait for use input
std::string dummy;
std::getline(std::cin, dummy);
}
//... Read file, fill structure, and return
std::string line;
while(std::getline(fileStream, line) && line!="")
{
//At this point, I can see that line is wrong
StringArray namedatearray=Utils::String::Split(line, "|");
assert(namedatearray.size()==2);
//Add data to my structure ( a map)
}
fileStream.close();
//return structure
}
bool OpenFileRead(const std::string& name, std::fstream& file)
{
file.open(name.c_str(), std::ios::in);
return !file.fail();
}
Thanks.
Edit: Of course, it was a mistake because I had two time the same file in two very similar path. Looking at the handle of the file open with process explorer (and not the relative file path made me found it).
Instead of thinking that this is due to some kind of "buffering", I would look for the obvious things first.
Are you sure the user is changing the same file that you're reading?
Are you certain reloading the data is properly updating your data structure in memory?
Are you confident that DataValid() is doing what you want?
The fact that the OS uses file buffers to increase disk performance is generally not visible from the application level. As long as you're looking at the same file, the OS knows that the user updated the file, and if you reopen it, then you'll see the changed data. If the data never even had a chance to get flushed to disk, that won't affect your application.

How to copy files in Visual C++?

I am using Visual C++. How to copy the content of this file to another file?
UINT32 writeToLog(wstring log)
{
wfstream file1 (LOG_FILE_NAME, ios_base::out);
file1 << log;
file1.close();
// want to copy file1 to file2
return 0;
}
What exactly do you want to do? If you need a copy of the data, you can read it in and write it back out again. If you really need a copy of the file, you have to use OS specific calls.
In many cases, reading in the file data and then writing it out again to a different file is a close enough approximation to a copy - like this:
ifstream file1(...);
ofstream file2(...);
std::copy(istream_iterator<char>(file1),istream_iterator<char>(),ostream_iterator<char>(file2));
However that really isn't a copy - it's creating a new file with the same contents. It won't correctly handle hard links or symlinks, it won't correctly handle metadata and it will only 'copy' the default file stream.
If you need a file copy on Windows you should call one of CopyFile, CopyFileEx or CopyFileTransacted depending on your exact requirements.
Standard C++ has no file copying facility, other than reading the file into memory and writing it out again to a different file. As you are using Windows, you can use the CopyFile function - other OSs have similar, OS-specific functions.
The above code from Joe Gauterin did not work for me. I was trying to copy a .tga image file, so maybe something about istream_iterator<char> screwed it up. Instead I used:
ifstream file1(...);
ofstream file2(...);
char ch;
while(file1 && file1.get(ch))
{
file2.put(ch);
}