Saving a file to a network in Qt - c++

I need to save a file to my company's network. This needs to be coded into my application not using a File Dialog box or anything. When I save the file without specifying a path it saves it completely fine in the directory that my application is in but when I try to do it the network nothing happens. This is what I have to save it.
QFile outfile;
outfile.setFileName("//DTPRIMARY/MyFile.htm");
outfile.open(QIODevice::WriteOnly);
QTextStream out(&outfile);
out << textEdit->toHtml();
out.flush();
outfile.close();
I actually want to save it here \\DTPRIMARY\Inetpub\wwwroot but took out the other folders thinkging that could have been part of the problem but it wasn't. And I'm using '/'s instead of '\'s because thats what a few places said to do (I've never really understood why file paths have to use '\' or '/' though so it could be wrong idk.)
Does anyone know how to do this/what's wrong with my code?

UNC paths should work perfectly normally, you can test this with a local file eg "\\?\C:\MyFile.htm" would be a file called MyFile.htm in the top of the C drive
Normally the path would be \\machine\share eg \\dtprimaray\share\MyFile.htm
The reason for using "/" is that the C language uses \ to mean the next char is special, so \t is tab, \n is newline. DOS was copied (sorry influenced by) an earlier OS that used "/" for file separators and Microsoft didn't want DOS to look too much like a copy. It's been a source of bugs ever since.
You can use \\ to say to C the next \ is really a \ - but it's easy to make mistakes when you have to write \\\\ to mean \\ and \\ to mean \ - so Windows lets you use /
Just tested it on my machine
QFile file("//machinename/downloads/MyFile.htm");
file.open(QIODevice::WriteOnly);
file.write("blah");
file.close();

Related

QT resources doesn't work

I'm writing a program that is supposed to work on the other computer, so I need to have my .txt files with it.
I have created a QT resource file and added one .txt file, then I used it in three windows. It worked perfectly fine until I added another .txt file to resource that is being used in only one window.
So I have users.txt file from which I am logging to program and managing users accounts and I have cars.txt which is a database for cars.
QFile text(":konta/users.txt");
text.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream wczytaj(&text);
This part works but in the next window
QFile text(":konta/users.txt");
text.open(QIODevice::ReadOnly);
QTextStream wczytaj(&text);
This part doesn't work, I have function which checks if file is open and if it exists, and they returns that it exists but is not open.
and now the newest window:
QFile baza(":/auta/cars.txt");
baza.open(QIODevice::Append | QIODevice::Text);
QTextStream zapisz(&baza);
if(!baza.exists()){QMessageBox::warning(this,"Uwaga","Baza nie została odnaleziona");}
else if(!baza.isOpen()){QMessageBox::warning(this,"Uwaga","Baza nie została otworzona");}
Same issue here, the file exists but is not opened. It's weird that it works in one window. Before I added the second .txt file, all the cases worked (except the third part of the code which didn't exist at that time). I didn't change anything in those files or functions.
I should also add that if I give them full path to the file C/folder/folder/file.txt, it works with no problems, but I need it to work on other computers as well, so it's not good for me.
I suppose that problem may be with currents path. When you start your application from Qt Designer current path is ../ (parent of the current directory). When your start your application directly default path is ./ (current directory where your .exe is). You may use this code to get universal path to default directory:
QString path = QApplication::applicationDirPath() % "/";
By the way you may use QFileDialog class to let you user choose files manually. And it is better to use SqLite for storing you users, cars etc. than text files. Qt provides in-built support for SqLite - it it fast and easy to use.

ARM Embedded Linux (AM335x), Text File Contents Deleted After Power Off

Kernel: 3.12.30-AM335x-PD15.2.1 (by PHYTEC)
My application requires editing a text file on run time and using it contents next time it powers on. So I created a text file in which I write a simple text, "Disable" or "Enable" using the program I have written with QT C++.
What I realized is, after the program writes the simple text, if I use the command "reboot" on bash, and wait for the program to reboot before I power off the the system (by plugging off its cable), "cat TextFile.txt" command yields "Enable" or "Disable", whichever the program has last written correctly.
However if I don't do a reboot and power the system off right away, and then power on again, the text file remains but the contents are deleted, so "cat TextFile.txt" yields nothing.
I tried to do the same manually, using the below methods:
Method 1:
echo Disable > TextFile.txt
reboot
.....wait for it to reboot
cat TextFile.txt
The results is "Disable".
Method 2:
echo Disable > TextFile.txt
.. power off by plugging off the cable
.. power on the system
cat TextFile.txt
No resulting text..
I simply don't want to have to reboot the system for the files to be saved. So I would be happy with executing commands within my QT C++ program to save everything without a reboot; but I do not know the operating system very well, therefore I do not know what is it that I should do to be able to do this.
This is my code my by the way:
QFile file(filename);
// Trying to open in WriteOnly and Text mode
if(!file.open(QFile::WriteOnly |
QFile::Text))
{
qDebug() << " Could not open file for writing";
}
// To write text, we use operator<<(),
// which is overloaded to take
// a QTextStream on the left
// and data types (including QString) on the right
QTextStream out(&file);
out << "Enable";
file.flush();
file.close();
As your experiement on the shell has shown this is not strictly a c++ or Qt matter, the file is just not written to disk right away.
The system setup is likely using delayed writing to optimize disk access times, i.e. first writing into in-memory buffers and writing to actual disk every once in a while.
You might want to tune that if you have other programs that write files and expect power loss as a realistic scenario.
Now, for the Qt program in question, you could try using QSaveFile instead of QFile, its commit() asks the system to actually sync to disk.

Recovering Files on Windows and C

Well this time I'm trying to write a program in C which recover deleted files from a disk, it could be an external disk, I have an idea than i had used before on linux, it is to open the disk as a kind of file and scaning the Headers and file footers of everything within the disk, the point is I'm not sure if there's allow on windows to open a disk as an File, basiclly I have the logic how to develope this program, but I'm not sure how to implement it on windows, anybody can give me a hand with this?.
The code I used on linux to open a disk as a file was:
Edit: That was a sample of what I was using guys, it's just to give you an idea of what I was doing, the correct syntax I used was the next:
direccion = ui->linea->text().toLatin1().constData();
f = fopen(direccion,"rb");
I used QT creator on linux, and direccion variable was a TextField value which contained the file path of the disk through a button function that open a QFileDialog...
could I use it in windows as well?
Thank you before hand..
"The code I used on linux to open a disk as a file was:"
File *f = fopen("E:\", "rb");
I seriously doubt you ever got this code working on any linux system (or windows either).
You'll need to escape the backslash path delimiter, if it's presented in any string literal:
FILE* f = fopen("E:\\", "rb");
// ^
Also all that filesystem path style you are presenting to access a particular disk, is about accessing a windows file path/disk.
No linux file system has notion about drive characters, and the file path delimiter value used is '/', not '\\'.
To recover deleted files, you can't use fopen or fstream::open because the file was deleted. Check the return value from the function or test the stream state.
The way to recover deleted files is:
Get the Master File Table as raw data.
Search for the record containing a string similar to the deleted
filename.
Change the entry in the Master File Table to "undeleted".
Write the Master File Table back to the drive.
The above usually requires platform specific API, which is different on Linux and Windows platforms.

Use of `ofstream` appears not to create nor write to file

At the end of a simulation, I want to write some results as an appended row to a data file. The code I am using is the following, where you can assume that outFile was correctly allocated as an std::ofstream, that output_file is a std::string containing a valid path to a file that does not yet exist, and that the variables printed out to the file are just int types that get values during the simulation.
outFile.open(output_file.c_str(), std::ios::out | std::ios::app );
outFile << num_nodes << ", " << tot_s << ", " << tot_c << ", " << tot_d << std::endl;
outFile.close();
I've checked whether it correctly opens the file with the ofstream::is_open() function and it returns false. However, I can't figure out why. I've tried it with many different file names and directory paths, all of which I have checked and they are valid (no typos, etc.)
The file being written is just into a folder on the desktop where I create files all the time, so I don't see how it could be a permissions issue. If it was a permissions issue, how can I check that?
Otherwise, what else can be preventing it from writing to the file?
Added:
Following up on the comments, after adding a call to perror(), it is displaying the "No such file or directory" error. The file path in question is:
/home/ely/Desktop/Evolutionary_Dynamics/GamesOnCycle/data/test.data
I want this file to be created, and all the directories in that path exist, it's all spelled correctly, etc., and there are no weird permission issues with the GamesOnCycle folder or its data subfolder. Note that it is a linux system (Ubuntu 11.04) so the forward slashes are correct for the file path, unless I'm missing something that C++ has to have w.r.t. file paths.
This could be happening due to several reasons.
1) The file is already open.
2) All the directories in the file path are not created.
3) Lack of file permissions.
For an additional reference, please see When will ofstream::open fail?
This may sound bad, but are you on windows or linux? If windows, for your file path, do you have it defined with double "\" in your string, or just one? If just one, you aren't putting the characters in your path that you think you are. To be safe, use the "/" character.
So if you had this:
string pathname = "C:\Users\me\Desktop";
That is NOT a valid path. You are escaping "\U", "\m" and "\D" into your string. You'd need this:
string pathname = "C:\\Users\\me\\Desktop";
or
string pathname = "C:/Users/me/Desktop";
The "/" isn't an escape character.
It's what seems likely to me.

Write a file in a specific path in C++

I have this code that writes successfully a file:
ofstream outfile (path);
outfile.write(buffer,size);
outfile.flush();
outfile.close();
buffer and size are ok in the rest of code.
How is possible put the file in a specific path?
Specify the full path in the constructor of the stream, this can be an absolute path or a relative path. (relative to where the program is run from)
The streams destructor closes the file for you at the end of the function where the object was created(since ofstream is a class).
Explicit closes are a good practice when you want to reuse the same file descriptor for another file. If this is not needed, you can let the destructor do it's job.
#include <fstream>
#include <string>
int main()
{
const char *path="/home/user/file.txt";
std::ofstream file(path); //open in constructor
std::string data("data to write to file");
file << data;
}//file destructor
Note you can use std::string in the file constructor in C++11 and is preferred to a const char* in most cases.
Rationale for posting another answer
I'm posting because none of the other answers cover the problem space.
The answer to your question depends on how you get the path. If you are building the path entirely within your application then see the answer from #James Kanze. However, if you are reading the path or components of the path from the environment in which your program is running (e.g. environment variable, command-line, config files etc..) then the solution is different. In order to understand why, we need to define what a path is.
Quick overview of paths
On the operating systems (that I am aware of), a path is a string which conforms to a mini-language specified by the operating-system and file-system (system for short). Paths can be supplied to IO functions on a given system in order to access some resource. For example here are some paths that you might encounter on Windows:
\file.txt
\\bob\admin$\file.txt
C:..\file.txt
\\?\C:\file.txt
.././file.txt
\\.\PhysicalDisk1\bob.txt
\\;WebDavRedirector\bob.com\xyz
C:\PROGRA~1\bob.txt
.\A:B
Solving the problem via path manipulation
Imagine the following scenario: your program supports a command line argument, --output-path=<path>, which allows users to supply a path into which your program should create output files. A solution for creating files in the specified directory would be:
Parse the user specified path based on the mini-language for the system you are operating in.
Build a new path in the mini-language which specifies the correct location to write the file using the filename and the information you parsed in step 1.
Open the file using the path generated in step 2.
An example of doing this:
On Linux, say the user has specified --output-path=/dir1/dir2
Parse this mini-language:
/dir1/dir2
--> "/" root
--> "dir1" directory under root
--> "/" path seperator
--> "dir2" directory under dir1
Then when we want to output a file in the specified directory we build a new path. For example, if we want to output a file called bob.txt, we can build the following path:
/dir1/dir2/bob.txt
--> "/" root
--> "dir1" directory under root
--> "/" path separator
--> "dir2" directory under dir1
--> "/" path seperator
--> "bob.txt" file in directory dir2
We can then use this new path to create the file.
In general it is impossible to implement this solution fully. Even if you could write code that could successfully decode all path mini-languages in existence and correctly represent the information about each system so that a new path could be built correctly - in the future your program may be built or run on new systems which have new path mini-languages that your program cannot handle. Therefore, we need to use a careful strategy for managing paths.
Path handling strategies
1. Avoid path manipulation entirely
Do not attempt to manipulate paths that are input to your program. You should pass these strings directly to api functions that can handle them correctly. This means that you need to use OS specific api's directly avoiding the C++ file IO abstractions (or you need to be absolutely sure how these abstractions are implemented on each OS). Make sure to design the interface to your program carefully to avoid a situation where you might be forced into manipulating paths. Try to implement the algorithms for your program to similarly avoid the need to manipulate paths. Document the api functions that your program uses on each OS to the user - this is because OS api functions themselves become deprecated over time so in future your program might not be compatible with all possible paths even if you are careful to avoid path manipulation.
2. Document the functions your program uses to manipulate paths
Document to the user exactly how paths will be manipulated. Then make it clear that it is the users responsibility to specify paths that will work correctly with the documented program behavior.
3. Only support a restricted set of paths
Restrict the path mini-languages your program will accept until you are confident that you can correctly manipulate the subset of paths that meet this set of restrictions. Document this to the user. Error if paths are input that do not conform.
4. Ignore the issues
Do some basic path manipulation without worrying too much. Accept that your program will exhibit undefined behavior for some paths that are input. You could document to the user that the program may or may not work when they input paths to it, and that it is the users responsibly to ensure that the program has handled the input paths correctly. However, you could also not document anything. Users will commonly expect that your program will not handle some paths correctly (many don't) and therefore will cope well even without documentation.
Closing thoughts
It is important to decide on an effective strategy for working with paths early on in the life-cycle of your program. If you have to change how paths are handled later it may be difficult to avoid a change in behaviour that might break the your program for existing users.
Try this:
ofstream outfile;
string createFile = "";
string path="/FULL_PATH";
createFile = path.as<string>() + "/" + "SAMPLE_FILENAME" + ".txt";
outfile.open(createFile.c_str());
outfile.close();
//It works like a charm.
That needs to be done when you open the file, see std::ofstream constructor or open() member.
It's not too clear what you're asking; if I understand correctly, you're
given a filename, and you want to create the file in a specific
directory. If that's the case, all that's necessary is to specify the
complet path to the constructor of ofstream. You can use string
concatenation to build up this path, but I'd strongly recommend
boost::filesystem::path. It has all of the functions to do this
portably, and a lot more; otherwise, you'll not be portable (without a
lot of effort), and even simple operations on the filename will require
considerable thought.
I was stuck on this for a while and have since figured it out. The path is based off where your executable is and varies a little. For this example assume you do a ls while in your executable directory and see:
myprogram.out Saves
Where Saves is a folder and myprogram.out is the program you are running.
In your code, if you are converting chars to a c_str() in a manner like this:
string file;
getline(cin, file, '\n');
ifstream thefile;
thefile.open( ("Saves/" + file + ".txt").c_str() );
and the user types in savefile, it would be
"Saves/savefile.txt"
which will work to get to to get to savefile.txt in your Saves folder. Notice there is no pre-slashes and you just start with the folder name.
However if you are using a string literal like
ifstream thefile;
thefile.open("./Saves/savefile.txt");
it would be like this to get to the same folder:
"./Saves/savefile.txt"
Notice you start with a ./ in front of the foldername.
If you are using linux, try execl(), with the command mv.