how to convert filesystem path to string - c++

I am iterating through all the files in a folder and just want their names in a string. I want to get a string from a std::filesystem::path. How do I do that?
My code:
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::experimental::filesystem;
int main()
{
std::string path = "C:/Users/user1/Desktop";
for (auto & p : fs::directory_iterator(path))
std::string fileName = p.path;
}
However I get the following error:
non-standard syntax; use '&' to create a pointer to a member.

To convert a std::filesystem::path to a natively-encoded string (whose type is std::filesystem::path::value_type), use the string() method. Note the other *string() methods, which enable you to obtain strings of a specific encoding (e.g. u8string() for an UTF-8 string).
C++17 example:
#include <filesystem>
#include <string>
namespace fs = std::filesystem;
int main()
{
fs::path path{fs::u8path(u8"愛.txt")};
std::string path_string{path.u8string()};
}
C++20 example (better language and library UTF-8 support):
#include <filesystem>
#include <string>
namespace fs = std::filesystem;
int main()
{
fs::path path{u8"愛.txt"};
std::u8string path_string{path.u8string()};
}

The examples given in the accepted answer, using the UTF-8 operations, are fine and a good guideline. There is just one error in the introductory explanation given in the answer, which Windows/MSVC developers should be aware of:
The string() method does not return the natively-encoded string (which would be std::wstring() on Windows), but rather it always returns a std::string. It also tries to convert the path to the local encoding, which is not always possible, if the path contains a unicode character not representable in the current code page and then the method throws an exception!
If you actually want the behavior that is described in the answer (method returns native string, i.e., std::string on Linux and std::wstring on Windows), you would have to use the native() method or the implicit conversion based on std::filesystem::path::operator string_type(), but as #tambre correctly pointed out in the examples, you should consider using the UTF-8 versions throughout.

In C++ 17 and above, you can use .generic_string() to convert the path to a string: https://en.cppreference.com/w/cpp/filesystem/path/generic_string.
The following is an example that gets the current working directory and converts it into a string.
#include <string>
#include <filesystem>
using std::filesystem::current_path;
int main()
{
filesystem::path directoryPath = current_path();
string stringpath = directoryPath.generic_string();
}

Related

How do I convert a std::filesystem::directory_entry to a std::string? [duplicate]

I have a loop that run through the whole directory I need to get a path from each file in order to use it.
This is my method
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
for (const auto & entry : fs::directory_iterator(sourceDir))
{
if (fs::is_directory(entry))
continue;
StreamRAII iStream{ entry, StreamMode::READ_BINARY };
}
issue is that StreamRAII constructor have to get std::string as its first parameter
StreamRAII(const std::string& filename, const char *mode);
But this const auto & entry : fs::directory_iterator(sourceDir), entry is derectory_entry type.
Question is, how to get path to my file? How to convert derectory_entry to std::string or char[]?
P.S. when I use cout I can see this path to my files...
derectory_entry has a path() function that returns a std::filesystem::path that holds the path name of the file. You can use it's string() function to get a std::string from that path. That would make your code look like
StreamRAII iStream{ entry.path().string(), StreamMode::READ_BINARY };
If you want to have to path from a file, use the .path() method of the directory_iterator class.
If you want to get a string from this path, just use the .string() method on your path object.
I have no clue what is StreamRAII that everybody here seems to know about. Here is the standard C++ code that probably induces the inspiration into the direction of the right answer of the OP question.
// $ g++ prog.cc -Wall -Wextra -std=c++17
#include <iostream>
#include <fstream>
#include <string>
#include <filesystem>
struct StreamRAII final {
StreamRAII(const std::string& filename, const char *mode)
{
using namespace std;
cout << "\n\nInside StreamRAII(const std::string& filename, const char
*mode)\n\nFilename: " << filename.c_str() << "\n\nmode: " << mode ;
}
};
int main()
{
namespace fs = std::filesystem;
for (const auto & entry : fs::directory_iterator("."))
{
if (fs::is_directory(entry))
continue;
StreamRAII iStream{ entry.path(), "StreamMode::READ_BINARY" };
}
return 0 ;
}
looking into the cppreference (en.cppreference.com/w/cpp/filesystem/path ---- snag.gy/0hJEaD.jpg) and using g++ this works fine ... but as of today latest and updated VS2019 does not compile the code above.
To make this platform independent with C++17, you must ensure that StreamRAII either accepts a std::filesystem::path or that the contract for the std::string input is that it must be UTF-8-encoded, then you must use it in this way and it won't perform any conversion on typical POSIX-systems (but perhaps on others (such as MSVC)). It won't work with C++20 though
StreamRAII iStream{ entry.path().u8string(), StreamMode::READ_BINARY };
If you have no control over StreamRAII you can only convert the path to a std::string (as other stated) and keep your fingers crossed that it will work anyway. This will compile with C++20 but if it works or not is (probably) system dependent
StreamRAII iStream{ entry.path().string(), StreamMode::READ_BINARY };

Create file in arabic name in c++

I want to create file having arabic name in C++. Below is the program that I tried.
#include <iostream>
#include <fstream>
#include <string>
int main() {
const char *path="D:\\user\\c++\\files\\فثسف.txt";
std::ofstream file(path); //open in constructor
std::string data("Hello World");
file << data;
return 0;
}
But file gets created with junk characters: ÙثسÙ.txt.
I am using windows platform and g++ compiler.
The default encoding for string literals can be specified with the -fexec-charset compiler option for gcc / g++.
In C++11 and later, can also use the u8, u, and U prefixes to strings to specify UTF8, UTF16, and UTF32 encodings:
const char * utf8literal = u8"This is an unicode UTF8 string! 剝Ц";
const char16_t * utf16literal = u"This is an unicode UTF16 string! 剝Ц";
const char32_t * utf32literal = U"This is an unicode UTF32 string! 剝Ц";
Using the above prefixes can upset some functions who aren't expecting these specific types of strings though; in general it may be better to set the compiler option.
There's a great writeup about this topic on this blog post: http://cppwhispers.blogspot.com/2012/11/unicode-and-your-application-3-of-n.html
I hope this helps. :)
Use UTF8:
#include <iostream>
#include <fstream>
#include <filesystem>
int main()
{
namespace fs = std::filesystem;
fs::path path { u8"فثسف.txt" };
std::ofstream file { path };
file << "Hello World";
return 0;
}
Using <filesystem> library may require additional compiler/linker options. GNU implementation requires linking with -lstdc++fs and LLVM implementation requires linking with -lc++fs

Strings as File names

If I set a string as a filename, it doesn't work and I have no idea why. (I'm using codeblocks and it seems to work on other IDEs)
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
string FileName="Test.txt";
ofstream File;
File.open(FileName);
}
This does not work,while this next one does:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream File;
File.open("Test.txt");
}
Error message:
no matching function for call to std::basic_ofstream::open(std::string&)
Can someone help a bit with this problem, I cannot understand why this error occurs.
Due to what should be considered a historical accident in the early era of C++ standardisation, C++ file streams originally didn't support std::string for filename parameters, only char pointers.
That's why something like File.open(FileName), with FileName being a std::string, didn't work and had to written as File.open(FileName.c_str()).
File.open("Test.txt") always worked because of the usual array conversion rules which allow the "Test.txt" array to be treated like a pointer to its first element.
C++11 fixed the File.open(FileName) problem by adding std::string overloads.
If your compiler doesn't support C++11, then perhaps you should get a newer one. Or perhaps it does support C++11 and you just have to turn on the support with a flag like -std=c++11.

How to convert string to wstring in C++

I have programmed some code but there is some problem. In this codes i am trying to convert string to wstring. But this string have "█" characters. This character have 219 ascii code.
This conversion getting error.
In my code:
string strs= "█and█something else";
wstring wstr(strs.begin(),strs.end());
After debugging, I am getting result like this
?and?something else
How do I correct this problem?
Thanks...
The C-library solution for converting between the system's narrow and wide encoding use the mbsrtowcs and wcsrtombs functions from the <cwchar> header. I've spelt this out in this answer.
In C++11, you can use the wstring_convert template instantiated with a suitable codecvt facet. Unfortunately this requires some custom rigging, which is spelt out on the cppreference page.
I've adapted it here into a self-contained example which converts a wstring to a string, converting from the system's wide into the system's narrow encoding:
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
// utility wrapper to adapt locale-bound facets for wstring/wbuffer convert
template <typename Facet>
struct deletable_facet : Facet
{
using Facet::Facet;
};
int main()
{
std::wstring_convert<
deletable_facet<std::codecvt<wchar_t, char, std::mbstate_t>>> conv;
std::wstring ws(L"Hello world.");
std::string ns = conv.to_bytes(ws);
std::cout << ns << std::endl;
}

Why can't I declare a string in my program: "string is undeclared identifier"

I can't declare a string in my program:
string MessageBoxText = CharNameTextBox->Text;
it just doesn't work. It says string is undeclared identifier. What am I missing in the namespace or include or something like that?
Make sure you've included this header:
#include <string>
And then use std::string instead of string. It is because string is defined in std namespace.
And don't write this at namespace scope:
using namespace std; //bad practice if you write this at namespace scope
However, writing it at function scope is not that bad. But the best is one which I suggested before:
Use std::string as:
std::string MessageBoxText = CharNameTextBox->Text;
To use the standard string class in C++ you need to #include <string>. Once you've added the #include directive string will be defined in the std namespace and you can refer to it as std::string.
E.g.
#include <string>
#include <iostream>
int main()
{
std::string hw( "Hello, world!\n" );
std::cout << hw;
return 0;
}
Are you by any way compiling using C++/CLI, the Microsoft extension for .NET, and not standard ISO C++?
In that case you should do the following:
System::String^ MessageBoxText = CharNameTextBox->Text;
Also see the following articles:
How to: Convert Between Various String Types
How to: Convert System::String to Standard String
How to: Convert Standard String to System::String