无法在C ++中使用西里尔文path读取文件

我试图读取文件,其中包含西里尔字符的path,并得到ifstream.is_open() == false这是我的代码:

 std::string ReadFile(const std::string &path) { std::string newLine, fileContent; std::ifstream in(path.c_str(), std::ios::in); if (!in.is_open()) { return std::string("isn't opened"); } while (in.good()) { getline(in, newLine); fileContent += newLine; } in.close(); return fileContent; } int main() { std::string path = "C:\\test\\документ.txt"; std::string content = ReadFile(path); std::cout << content << std::endl; return 0; } 

指定的文件存在

我试图在谷歌find解决scheme,但我什么都没有

这里是我看到的链接:

我不需要wstring

和以前一样

这里没有答案

不是关于C ++的

也没有答案

PS我需要得到文件的内容在string,而不是在wstring

这是编码我的IDE的设置(CLION 2017.1)

我的编码

你需要一个最新的编译器或Boost。 std::filesystem::path可以处理这些名字,但是它在C ++ 17标准中是新的。 你的编译器仍然可以把它作为std::experimental::filesystem::path ,否则你会使用第三方的boost::filesystem::path 。 接口与Boost版本的灵感相当。

std :: string的定义是std :: basic_string,所以你的西里尔字符不会按照预期存储。 至少,尝试使用std :: wstring来存储你的文件路径,然后你可以使用std :: string从文件读取。

首先,将你的项目设置设置为使用UTF-8编码,而不是windows-1251。 直到标准库变得非常好(不会很快),你基本上不能依靠它,如果你想妥善处理io。 为了使输入流从Windows上的文件中读取,您需要编写自己的自定义输入流缓冲区,该缓冲区使用2字节宽的字符打开文件,或者依赖于此类例程的某些第三方实现。 这里有一些不完整的(但足够你的例子)的实现:

 // assuming that usual Windows SDK macros such as _UNICODE, WIN32_LEAN_AND_MEAN are defined above #include <Windows.h> #include <string> #include <iostream> #include <system_error> #include <memory> #include <utility> #include <cstdlib> #include <cstdio> static_assert(2 == sizeof(wchar_t), "wchar_t size must be 2 bytes"); using namespace ::std; class MyStreamBuf final: public streambuf { #pragma region Fields private: ::HANDLE const m_file_handle; private: char m_buffer; // typically buffer should be much bigger #pragma endregion public: explicit MyStreamBuf(wchar_t const * psz_file_path) : m_file_handle(::CreateFileW(psz_file_path, FILE_GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) , m_buffer{} { if(INVALID_HANDLE_VALUE == m_file_handle) { auto const error_code{::GetLastError()}; throw(system_error(static_cast< int >(error_code), system_category(), "::CreateFileW call failed")); } } public: ~MyStreamBuf(void) { auto const closed{::CloseHandle(m_file_handle)}; if(FALSE == closed) { auto const error_code{::GetLastError()}; //throw(::std::system_error(static_cast< int >(error_code), system_category(), "::CloseHandle call failed")); // throwing in destructor is kinda wrong // but if CloseHandle returned false then our program is in inconsistent state // and must be terminated anyway (void) error_code; // not used abort(); } } private: auto underflow(void) -> int_type override { ::DWORD bytes_count_to_read{1}; ::DWORD read_bytes_count{}; { auto const succeeded{::ReadFile(m_file_handle, addressof(m_buffer), bytes_count_to_read, addressof(read_bytes_count), nullptr)}; if(FALSE == succeeded) { auto const error_code{::GetLastError()}; setg(nullptr, nullptr, nullptr); throw(system_error(static_cast< int >(error_code), system_category(), "::ReadFile call failed")); } } if(0 == read_bytes_count) { setg(nullptr, nullptr, nullptr); return(EOF); } setg(addressof(m_buffer), addressof(m_buffer), addressof(m_buffer) + 1); return(m_buffer); } }; string MyReadFile(wchar_t const * psz_file_path) { istream in(new MyStreamBuf(psz_file_path)); // note that we create normal stream string new_line; string file_content; while(in.good()) { getline(in, new_line); file_content += new_line; } return(::std::move(file_content)); } int main(void) { string content = MyReadFile(L"C:\\test\\документ.txt"); // note that path is a wide string cout << content << endl; return 0; } 

更改您的代码使用wstring并保存您的文件使用Unicode编码(非UTF8之一,使用USC-2,UTF16或类似的东西)。 MSVC有非标准的过载,特别是因为这个原因能够处理文件名中的非ASCII字符:

 std::string ReadFile(const std::wstring &path) { std::string newLine, fileContent; std::ifstream in(path.c_str(), std::ios::in); if (!in) return std::string("isn't opened"); while (getline(in, newLine)) fileContent += newLine; return fileContent; } int main() { std::wstring path = L"C:\\test\\документ.txt"; std::string content = ReadFile(path); std::cout << content << std::endl; } 

另外,请注意更正的ReadFile代码。