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

发布于 2024-12-07 17:04:36 字数 1781 浏览 1 评论 0原文

当我尝试将一段 C++ 代码从 MSWindows 移植到 Linux (Mint10) 时,我偶然发现了一个奇怪的问题。我发现硬编码文件名中有一个小拼写错误:尾随空格字符(\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 的正常行为吗?还有其他问题吗?我用谷歌搜索但没有找到有关此案例的参考资料。 (也许我是一个糟糕的谷歌者:))
  • 如何编写一个以严格的方式使用文件名工作的代码?在将文件名传递给某些文件函数之前始终修剪文件名并不是我的情况的解决方案;我当前的应用程序必须列出目录(使用boost::filesystem::directory_iterator),如果用户提供带有尾随空格字符的文件名(这种情况很少见,但在许多文件系统上是允许的),修剪文件名将破坏应用程序)。

感谢您的任何建议!

I stumbled on a strange problem when trying to port a piece of C++ code from MSWindows to linux (Mint10). I discovered that there was a little typo in a hard-coded filename : a trailing space char (\x20).

The code worked like a charm under Windows (Windows Vista/7), but it had trouble to deal with the erroneous filename under linux. I discovered that both std::filebuf::open and std::fopen (and also boost::filesystem::filebuf) allow trailing space chars in filename under Windows (which I think is an incorrect behavior).

I tested the following code using MSVC2010 and MinGW under Win7 :

# 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 ;
}

I verified that the file on the harddrive has no trailing space characters in the name. The file was successfully opened on Windows, but no luck to access it under linux if the filename isn't an exact match.

So I have a couple of questions :

  • Is this a normal behavior of the file API under Windows ? And is there some other gotchas ? I googled but found no reference on this case. (Maybe I'm a bad googler :))
  • How to write a code that works in a strict fashion with filenames ? Always trimming filenames before passing them to some file function isn't the solution for my case ; my current app have to list directories (using boost::filesystem::directory_iterator) and trimming filenames will break the app if the user provides filenames with trailing space chars (which is rare but allowed on many file systems).

Thanks for any advice !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

空‖城人不在 2024-12-14 17:04:36

Windows 本身会去除文件名中的尾随空格,它与您用来打开文件的 C++ 函数无关。

以下是 Windows API 函数 CreateFile 中对此行为的一个引用:信息:不支持以空格或句点结尾的文件名

Windows itself will strip the trailing blanks from a filename, it has nothing to do with the C++ function you use to open the file.

Here's one reference to this behavior in the Windows API function CreateFile: INFO: Filenames Ending with Space or Period Not Supported

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文