我正在尝试读取其路径中包含西里尔字符的文件,并获得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;
}
指定的文件存在
我正试图在谷歌找到解决方案,但我什么都没得到
这是链接,我看到了:
P.S。我需要在string中获取文件内容,而不是在wstring
中这是编码我的IDE的设置(CLION 2017.1)
答案 0 :(得分:1)
您需要一个最新的编译器或Boost。 std::filesystem::path
可以处理这些名称,但它是C ++ 17标准中的新名称。您的编译器可能仍然将其作为std::experimental::filesystem::path
,否则您将使用第三方boost::filesystem::path
。界面非常具有可比性,因为Boost版本是灵感。
答案 1 :(得分:0)
std :: string的定义是std :: basic_string,因此您的Cyrillic chararecters不会按预期存储。至少,尝试使用std :: wstring存储文件路径,然后使用std :: string从文件中读取。
答案 2 :(得分:0)
首先,将项目设置设置为使用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;
}
答案 3 :(得分: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
代码。