为什么Windows上的std :: fopen和std :: filebuf :: open修剪尾随空格字符?

时间:2011-09-29 21:08:58

标签: c++ filesystems std

在尝试将一些C ++代码从MSWindows移植到linux(Mint10)时,我偶然发现了一个奇怪的问题。我发现硬编码的文件名中有一个小错字:尾随空格char(\ x20)。

代码在Windows(Windows Vista / 7)下就像一个魅力,但它在处理linux下的错误文件名时遇到了麻烦。我发现std::filebuf::openstd::fopen(以及boost::filesystem::filebuf)允许Windows下的文件名中的尾随空格字符(我认为这是一种不正确的行为)。

我在Win7下使用MSVC2010和MinGW测试了以下代码:

# include <iostream>
# include <fstream>
# include <string>
# include <cstdlib>

const std::string filename = "Z:\\Path\\To\\A\\File " ;  // one trailing space

int main(int, char * [])
{
    std::cout << "Testing with file : \"" << filename << "\"" << std::endl ;

    // Testing with std::filebuf::open
    std::filebuf fb ;
    fb.open(filename.c_str(), std::ios::in | std::ios::binary) ;
    if( fb.is_open() )
    {
        std::cout << "Using std::filebuf : Opened" << std::endl ;
        fb.close() ;
    }
    else
    {
        std::cout << "Using std::filebuf : Not opened" << std::endl ;
    }

    // Testing with std::fopen
    std::FILE * fp = std::fopen(filename.c_str(), "rb") ;
    if( fp )
    {
        std::cout << "Using std::fopen : Opened" << std::endl ;
        std::fclose(fp) ;
    }
    else
    {
        std::cout << "Using std::fopen : Not opened" << std::endl ;
    }
    return 0 ;
}

我确认硬盘上的文件名称中没有尾随空格字符。该文件已在Windows上成功打开,但如果文件名不完全匹配,则无法在linux下访问该文件。

所以我有几个问题:

  • 这是Windows下文件API的正常行为吗?还有其他一些陷阱吗?我用谷歌搜索,但没有找到关于这个案例的参考。 (也许我是一个糟糕的googler:))
  • 如何使用文件名编写严格的代码?在将文件名传递给某个文件函数之前,总是修剪文件名不是我案例的解决方案;我当前的应用程序必须列出目录(使用boost::filesystem::directory_iterator),如果用户提供带有尾随空格字符的文件名,则修剪文件名将破坏应用程序(这种情况很少见,但允许在许多文件系统上使用)。

感谢您的任何建议!

1 个答案:

答案 0 :(得分:4)

Windows本身将从文件名中删除尾随空白,它与用于打开文件的C ++函数无关。

以下是Windows API函数CreateFile中对此行为的一个引用:INFO: Filenames Ending with Space or Period Not Supported