C++ ifstream long full path无法正常工作

uks*_*son 0 c++ qt

我想从磁盘读取文件,在程序执行期间使用QDialog(Qt Widget)我选择文件的路径.一段代码很简单:

ifstream infile(path.c_str());

if (infile.is_open()) {
    //some code   
}
else
    //log it
Run Code Online (Sandbox Code Playgroud)

问题出现取决于目标文件的位置:

  • 如果文件的路径是"D:\ folder\file" - 它会读取文件,一切正常
  • 如果文件的路径是"C:\ Users \RafałSurname\ Desktop\folder\file" - 文件无法打开

怎么解决这个问题?

Che*_*Alf 8

猜测,您的计算机的Windows ANSI(返回的代码页GetACP)不包含"?"您名称中的字符.

最简单的解决方案是不在路径中使用这样的字符.

否则,你可以使用全路径,wchar_t基于路径.即使标准C++没有,Visual C++也支持它们.

或者,要使代码也可以使用g ++,您可以使用Windows API将宽路径转换为短路径,其中每个名称最多8个字符.短文件夹和文件名是交替使用,旨在与非Unicode软件兼容.然而,虽然对于手头的情况(即打开文件)可以很好地轻松地工作,但创建文件会更复杂.

最后,您可以使用Boost文件系统,它与将成为C++ 14一部分的功能非常相似.显然,版本/变体已经是Visual C++运行时库的一部分.然而,问题在于它可能无法与g ++一起使用,因为它依赖于Visual C++中前面提到的宽路径支持(是的,它几乎是一个悖论,在标准中获得具有此类要求的库).


在g ++的标准库实现中有一些低级Unicode路径支持,但不是像wchar_t基于提供的构造器那样.我深入研究了我的一些旧代码并找到了下面的代码.cppx::Syschar是我的代码定义的类型,它wchar_t在Windows中具有基础类型:

文件"open_file.h"
#pragma once

#include <stdio.h>      // fopen        !!!Needs to be first for g++ 4.7.2.
#include <rfc/cppx/core/Syschar.h>      // cppx::Syschar etc.
#include <wchar.h>      // _wfopen

namespace x {
    using cppx::Syschar;

    inline auto open_file( char const* const path, char const* const options )
        -> FILE*
    { return ::fopen( path, options ); }

    inline auto open_file( wchar_t const* const path, wchar_t const* const options )
        -> FILE*
    { return _wfopen( path, options ); }

    inline auto open_file( Syschar const* path, Syschar const* options )
        -> FILE*
    { return open_file( raw( path ), raw( options ) ); }
}  // namespace zx
Run Code Online (Sandbox Code Playgroud) 文件"ofstream.g ++ _ compiler.h"
#pragma once
#include "open_file.h"                  // open_file
#include <ext/stdio_filebuf.h>          // __gnu_cxx::stdio_filebuf

namespace x {
    using cppx::Syschar;

    class ofstream
        : public std::ofstream
    {
    private:
        __gnu_cxx::stdio_filebuf<char>  buf_;
        std::streambuf*                 p_original_buf_;

    public:
        ~ofstream()
        {
            basic_ios::rdbuf( p_original_buf_ );
            buf_.close();
        }

        ofstream( Syschar const* const filename )
            : std::ofstream()
            , buf_(
                open_file( filename, CPPX_U( "w" ) ),
                std::ios_base::out
                )
            , p_original_buf_( nullptr )
        {
            p_original_buf_ = basic_ios::rdbuf( &buf_ );
        }
    };

}  // namespace x
Run Code Online (Sandbox Code Playgroud)

当然这是一个ofstream,而不是一个ifstream.

而且,它只是g ++支持的一个例子,而你的问题的答案很可能涉及使用Visual C++中的宽路径支持,或使用Windows API,或者只是避免使用特定于Unicode的字符,如上所述.

利用Visual C++宽路径支持,类似的ofstream实现可以像这样:

文件"ofstream.msvc_compiler.h"
#pragma once

#include <rfc/cppx/core/Syschar.h>      // cppx::Syschar etc.

#include <fstream>      // std::ofstream

namespace x {
    using cppx::Syschar;

    class ofstream
        : public std::ofstream
    {
    public:
        // Other stuff, and ...
        ofstream( Syschar const* const filename )
            : std::ofstream( raw( filename ) )   // wchar_t, a Visual C++ extension.
        {}
    };
}  // namespace x
Run Code Online (Sandbox Code Playgroud)