Is there a default code in c++ to write a file(.txt) to a desktop, which could be used for any computer without knowing the leading /desktop?
The most portable way is to use Qt, namely QStandardPaths.
The standard library does not have any off-hand support for it, so you will either need to reinvent the wheel or find a robust solution that already exists. Qt is such a thing.
QStandardPaths::DesktopLocation 0 Returns the user's desktop directory.
In which case, you could use QFile as well as ofstream to write the file to that folder. You would only need to depend on QtCore for this.
The code would look like this:
#include <QFile>
#include <QStandardPaths>
#include <QDebug>
#include <QTextStream>
...
QFile file(QStandardPaths::locate(QStandardPaths::DesktopLocation, ""));
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
qDebug() << "Failed to open";
QTextStream out(&file);
// Done, yay!
This will gently work across distributions and operating systems that QtCore supports, including, but limited to:
Windows
Linux
Mac
QNX
and so forth.
Use SHGetKnownFolderPath with FOLDERID_Desktop (Vista and later), alternatively SHGetFolderPath with CSIDL_DESKTOP to obtain the folder that represents the desktop for the current user. Depends on your Windows version targets, there's several functions, and some of them deprecated.
Just use standard header fstream with getenv:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sstream>
using namespace std;
int main (int argc, char **argv)
{
if(argc != 2)
{
cerr << "usage: " << argv[0] << " filename" << endl;
return 1;
}
std::ostringstream oss;
#ifdef _WIN32
oss << getenv("HOMEDRIVE") << getenev("HOMEPATH");
#else
oss << getenv("HOME");
#endif
oss << "/" << argv[1];
ofstream f;
f.open (oss.str().c_str());
f << "bar";
f.close();
return 0;
}
Related
I'm currently new to C++ and I've been watching a tutorial series https://www.youtube.com/watch?v=_bYFu9mBnr4, but I'm having a big issue. My C++ code will not open a file no matter what I do, I've looked online and tried renaming it, the full path, everything I can think of. Here's my code,
#include <iostream>
#include <fstream>
#include <cstring>
#include <cerrno>
#include <filesystem>
int main()
{
std::ofstream file;
file.open("hello.txt");
if (!file.is_open())
{
std::cerr << "Error: " << strerror(errno) << '\n';
std::cout << std::filesystem::current_path() << std::endl;
}
file << "hello!";
file.close();
return 0;
}
Sorry about this question, it may have been a dumb issue. Turns out IT WAS my antivirus. Avast kept blocking it, it was just looking out for me. I decided to change my antivirus afterwards and it now works fine!
I have this short program:
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
int main (int argc, char * argv[]) {
std::string homedir = std::getenv("HOME");
std::string filename = argc > 1 ? argv[1] : (homedir + "/" + "file");
std::cout << homedir << std::endl;
std::cout << filename << std::endl;
std::fstream file;
file.open(filename, std::ios::out);
file << "Yo yo waddup" << std::endl;
file.close();
return 0;
}
When I supply no arguments, it opens a file in the users home directory. That of course makes sense. But when I run it from a different directory like this:
$ ./folder/hometest examplefile
The program creates "examplefile" in my current directory instead of the directory where the program is.
Why exactly is this happening?
Why exactly is this happening?
The program is behaving just as expected.
The file is opened relative to the current work directory, not where the executable is located.
If it didn't work that way,
All your programs will have to work with absolute paths, or
The location of the program will be flooded with files. First, that might not be possible because of permissions issue. Second, in a multi-user system, users will end up trying to create the same file names/directories.
Neither of the above is desirable.
In C++ I need to check whether a entered file name exists in that folder or not. I'm writing code for Linux, using the g++ compiler.
please help guys :)
I saw this code somewhere on net for my problem but I strongly feel it wont serve my purpose:
ofstream fout(filename);
if(fout)
{
cout<<"File name already exists";
return 1;
}
You can do this by testing with an ifstream, but there is a subtle difference between using that and the C level stat() interface.
#include <cerrno>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
using namespace std;
int main (int argc, const char *argv[]) {
if (argc < 2) {
cerr << "Filepath required.\n";
return 1;
}
ifstream fs(argv[1]);
if (fs.is_open()) {
fs.close();
cout << "ifstream says file exists.\n";
} else cout << "ifstream says file does not exist.\n";
struct stat info;
if ((stat(argv[1], &info)) == -1) {
if (errno == ENOENT) cout << "stat() says file does not exist.\n";
else cout << "stat() says " << strerror(errno) << endl;
} else cout << "stat() says file exists.\n";
return 0;
}
If you run this on a file that exists and you have read permission on, you'll get the same answer both ways.
If you run this on a file that does not exist, you get the same answer both ways.
If you run this on a file that exists but you do not have read permissions on, you'll get two different answers. fstream will say the file does not exist, but stat() will say it does. Note that if you run ls in the same directory, it will show the file, even though you cannot read it; it does exist.
So if the last case is not significant -- i.e., a file you can't read might as well not exist -- then use the ifstream test. However, if it is important, then use the stat() test. See man 2 stat (the 2 is important) for more, and remember, to use it you need:
#include <cerrno>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
cerrno is required to check errno if stat() fails, which can happen. For example, if read permission on a directory in the path is denied, then stat() will fail and errno will be equal to EACCES; if you try it with the above program you'll get stat() says Permission denied. This does not mean the file exists. It means you can't check whether it exists or not.
Beware, if you have not used errno before: You must check immediately on a failed call, before you make any others which may set it differently. It is, however, thread safe.
If you want to be cross-platform and C++'y I recommend the Boost Filesystem library.
For your purposes I think something similar to this Boost sample code
#include <iostream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main(int argc, char* argv[])
{
path p (argv[1]); // p reads clearer than argv[1] in the following code
if (exists(p)) // does p actually exist?
{
if (is_regular_file(p)) // is p a regular file?
cout << p << " size is " << file_size(p) << '\n';
else if (is_directory(p)) // is p a directory?
cout << p << "is a directory\n";
else
cout << p << "exists, but is neither a regular file nor a directory\n";
}
else
cout << p << "does not exist\n";
return 0;
}
would do the job.
Maybe what you want is fstat:
http://codewiki.wikidot.com/c:system-calls:fstat
I wrote the following program using VS2008:
#include <fstream>
int main()
{
std::wofstream fout("myfile");
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}
When I tried to compile it the IDE asked me whether I wanted to save my source file in unicode, I said "yes, please".
Then I run the program, and myfile appeared in my project's folder. I opened it with notepad, the file was empty. I recalled that notepad supported only ASCII data. I opened it with WordPad, it was still empty. Finally the little genius inside me urged me to look at the file size and not surprisingly it was 0 bytes. So I rebuilt and reran the program, to no effect. Finally I decided to ask very intelligent people on StackOverflow as to what I am missing and here I am :)
Edited:
After the abovementioned intelligent people left some comments, I decided to follow their advice and rewrote the program like this:
#include <fstream>
#include <iostream>
int main()
{
std::wofstream fout("myfile");
if(!fout.is_open())
{
std::cout << "Before: Not open...\n";
}
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
if(!fout.good())
{
std::cout << "After: Not good...\n";
}
}
Built it. Ran it. And... the console clearly read, to my surprise: "After: Not good...".
So I edited my post to provide the new information and started waiting for answers which would explain why this is and what I could do. :)
MSVC offers the codecvt_utf8 locale facet for this problem.
#include <codecvt>
// ...
std::wofstream fout(fileName);
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
In Visual studio the output stream is always written in ANSI encoding, and it does not support UTF-8 output.
What is basically need to do is to create a locale class, install into it UTF-8 facet and then imbue it to the fstream.
What happens that code points are not being converted to UTF encoding. So basically this would not work under MSVC as it does not support UTF-8.
This would work under Linux with UTF-8 locale
#include <fstream>
int main()
{
std::locale::global(std::locale(""));
std::wofstream fout("myfile");
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}
~
And under windows this would work:
#include <fstream>
int main()
{
std::locale::global(std::locale("Russian_Russia"));
std::wofstream fout("myfile");
fout << L"Россия" << std::endl;
}
As only ANSI encodings are supported by MSVC.
Codecvt facet can be found in some Boost libraries. For example: http://www.boost.org/doc/libs/1_38_0/libs/serialization/doc/codecvt.html
I found the following code working properly. I am using VS2019.
#include <iostream>
#include <fstream>
#include <codecvt>
int main()
{
std::wstring str = L"abàdëef€hhhhhhhµa";
std::wofstream fout(L"C:\\app.log.txt", ios_base::app); //change this to ios_base::in or ios_base::out as per relevance
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
fout << str;
fout.close();
}
I wrote the following program using VS2008:
#include <fstream>
int main()
{
std::wofstream fout("myfile");
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}
When I tried to compile it the IDE asked me whether I wanted to save my source file in unicode, I said "yes, please".
Then I run the program, and myfile appeared in my project's folder. I opened it with notepad, the file was empty. I recalled that notepad supported only ASCII data. I opened it with WordPad, it was still empty. Finally the little genius inside me urged me to look at the file size and not surprisingly it was 0 bytes. So I rebuilt and reran the program, to no effect. Finally I decided to ask very intelligent people on StackOverflow as to what I am missing and here I am :)
Edited:
After the abovementioned intelligent people left some comments, I decided to follow their advice and rewrote the program like this:
#include <fstream>
#include <iostream>
int main()
{
std::wofstream fout("myfile");
if(!fout.is_open())
{
std::cout << "Before: Not open...\n";
}
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
if(!fout.good())
{
std::cout << "After: Not good...\n";
}
}
Built it. Ran it. And... the console clearly read, to my surprise: "After: Not good...".
So I edited my post to provide the new information and started waiting for answers which would explain why this is and what I could do. :)
MSVC offers the codecvt_utf8 locale facet for this problem.
#include <codecvt>
// ...
std::wofstream fout(fileName);
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
In Visual studio the output stream is always written in ANSI encoding, and it does not support UTF-8 output.
What is basically need to do is to create a locale class, install into it UTF-8 facet and then imbue it to the fstream.
What happens that code points are not being converted to UTF encoding. So basically this would not work under MSVC as it does not support UTF-8.
This would work under Linux with UTF-8 locale
#include <fstream>
int main()
{
std::locale::global(std::locale(""));
std::wofstream fout("myfile");
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}
~
And under windows this would work:
#include <fstream>
int main()
{
std::locale::global(std::locale("Russian_Russia"));
std::wofstream fout("myfile");
fout << L"Россия" << std::endl;
}
As only ANSI encodings are supported by MSVC.
Codecvt facet can be found in some Boost libraries. For example: http://www.boost.org/doc/libs/1_38_0/libs/serialization/doc/codecvt.html
I found the following code working properly. I am using VS2019.
#include <iostream>
#include <fstream>
#include <codecvt>
int main()
{
std::wstring str = L"abàdëef€hhhhhhhµa";
std::wofstream fout(L"C:\\app.log.txt", ios_base::app); //change this to ios_base::in or ios_base::out as per relevance
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
fout << str;
fout.close();
}