读取windows文件; _stat 返回错误值

发布于 2024-12-13 03:55:21 字数 2682 浏览 5 评论 0原文

我的学校给了我一个小图书馆来做一些项目。这个图书馆是用 Linux 编写的,所以我试图改变一些东西来与我的 MinGW 编译器一起工作。一个特定的程序用于读取给定 URL 的文件。我必须将 stat 更改为 _stat 才能使其正常工作。打开文件工作正常,但 _stat 似乎返回不正确的值。我将在下面包含相关代码:

#ifdef WIN32
    #define stat _stat
#endif

    //return true if the number of chars read is the same as the file size
bool IsDone() const
{
    cout << "checking if numRead " << numRead << " is fileSize " << fileSize << endl;
    return (numRead == fileSize);
}

char Read()
{
    if (IsDone())
        throw IllegalStateException("stream is done");
    else
    {
        char c;
        file.get(c);
        cout << "reading: " << c << endl;
        if (file.fail())
            throw FileException(std::string("error reading from file ") + fileName);

        ++numRead;
        return c;
    }
}

void OpenFile(string fileName)
{
    struct stat buf;
    #ifdef WIN32
        if (_stat(fileName.c_str(), &buf) < 0){
            switch (errno){
                case ENOENT:
                  throw FileException(std::string("Could not find file ") + name);
                case EINVAL:
                    throw FileException(std::string("Invalid parameter to _stat.\n"));
                default:
                  /* Should never be reached. */
                    throw FileException(std::string("Unexpected error in _stat.\n"));
            }
        }
    #else
        if (stat(fileName.c_str(), &buf) < 0)
            throw FileException(std::string("could not determine size of file ") + fileName);
    #endif
        fileSize = buf.st_size;
        file.open(fileName.c_str());
}

如果您想查看整个库,可以从 此处。我知道代码看起来很恶心;我只是想找到一个可以工作的 Windows 版本。这个东西在 Linux 上运行得很好;问题是,当我在 Windows 上读取文件时,我在输入文件中使用的每个换行符的大小都短 1,因此,如果我有一个如下所示的文件:

 text

它工作正常,但是:

text\r\n
 

它会中断,输出如下所示:

checking if numRead 0 is fileSize 6
checking if numRead 0 is fileSize 6
reading: t
checking if numRead 1 is fileSize 6
checking if numRead 1 is fileSize 6
reading: e
checking if numRead 2 is fileSize 6
checking if numRead 2 is fileSize 6
reading: x
checking if numRead 3 is fileSize 6
checking if numRead 3 is fileSize 6
reading: t
checking if numRead 4 is fileSize 6
checking if numRead 4 is fileSize 6
reading:

checking if numRead 5 is fileSize 6
checking if numRead 5 is fileSize 6
reading:
File Error: error reading from file H:/test/data/stuff.txt

它中断是因为 IsDone() 错误地返回 false(没有双关语意图),并且程序尝试读取文件末尾之后的内容。关于为什么 _stat 在有换行符时返回错误数字的任何建议?

I was given a little library by my school to do some projects in. The library was written with linux in mind, so I'm trying to change some things to work with my MinGW compiler. One particular program is for reading files given a URL. I had to change stat to _stat to make it work properly. Opening a file works fine but _stat seems to return the incorrect value. I'll include the relevant code below:

#ifdef WIN32
    #define stat _stat
#endif

    //return true if the number of chars read is the same as the file size
bool IsDone() const
{
    cout << "checking if numRead " << numRead << " is fileSize " << fileSize << endl;
    return (numRead == fileSize);
}

char Read()
{
    if (IsDone())
        throw IllegalStateException("stream is done");
    else
    {
        char c;
        file.get(c);
        cout << "reading: " << c << endl;
        if (file.fail())
            throw FileException(std::string("error reading from file ") + fileName);

        ++numRead;
        return c;
    }
}

void OpenFile(string fileName)
{
    struct stat buf;
    #ifdef WIN32
        if (_stat(fileName.c_str(), &buf) < 0){
            switch (errno){
                case ENOENT:
                  throw FileException(std::string("Could not find file ") + name);
                case EINVAL:
                    throw FileException(std::string("Invalid parameter to _stat.\n"));
                default:
                  /* Should never be reached. */
                    throw FileException(std::string("Unexpected error in _stat.\n"));
            }
        }
    #else
        if (stat(fileName.c_str(), &buf) < 0)
            throw FileException(std::string("could not determine size of file ") + fileName);
    #endif
        fileSize = buf.st_size;
        file.open(fileName.c_str());
}

If you would like to see the entire library, you can get them from here. I understand that the code is gross looking; I'm just trying to cludge a working windows version. This thing works fine on Linux; the problem is that when I read in a file on Windows, the size is 1 short for every newline that I use in the input file, so that if I have a file that looks like this:

 text

It works fine, but with:

text\r\n
 

It breaks, and the output looks like this:

checking if numRead 0 is fileSize 6
checking if numRead 0 is fileSize 6
reading: t
checking if numRead 1 is fileSize 6
checking if numRead 1 is fileSize 6
reading: e
checking if numRead 2 is fileSize 6
checking if numRead 2 is fileSize 6
reading: x
checking if numRead 3 is fileSize 6
checking if numRead 3 is fileSize 6
reading: t
checking if numRead 4 is fileSize 6
checking if numRead 4 is fileSize 6
reading:

checking if numRead 5 is fileSize 6
checking if numRead 5 is fileSize 6
reading:
File Error: error reading from file H:/test/data/stuff.txt

It breaks because IsDone() falsely returns false (no pun intented), and the program tries to read past the end of the file. Any suggestions on why _stat is returning an incorrect number when there's a newline?

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

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

发布评论

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

评论(2

潦草背影 2024-12-20 03:55:21

_stat 返回的内容非常正确。 Windows 使用“\r\n”来表示行结束,但是当您以文本模式打开文件时,它会在您读取流时转换为单个换行符。

如果您希望读取的流与外部长度匹配,请改为以二进制模式打开文件。

如果你能原谅我这么说,一旦你完成了这个,我的建议是扔掉这个代码,并更改你的名字,这样如果有人看到你的帖子,他们就不会因此责怪你。这里有很多代码,至少对我来说,似乎使简单的任务变得更加复杂和困难。

What _stat is returning is quite correct. Windows uses "\r\n" to signal the end of a line, but when you open a file in text mode, that will be converted to a single new-line character as you read the stream.

If you want the stream you read to match the external length, open the file in binary mode instead.

If you'll pardon my saying so, once you're done with that, my advice would be to throw this code away, and change your name so if somebody sees your post, they won't blame you for it. What you have here is a lot of code that seems, at least to me, to make a simple task considerably more complex and difficult.

旧梦荧光笔 2024-12-20 03:55:21

在我看来,您应该以二进制模式打开文件。不知道为什么需要使用 stat 来读取文件,并且在代码的 Windows 版本中,您调用 _stat,然后再次调用 stat。

在 Windows 中,有几种方法可以实现此目的。我个人的偏好是使用类似的东西:

char strBuffer[1024];

FILE *fp = fopen (file,"rb");  // Binary read mode
while (!feof (fp))
   fread (strBuffer,1,sizeof (strBuffer),fp);

fclose (fp);

Looks to me like you should open the file with binary mode. No idea why you need to use stat to read a file and in the Windows version of your code, you call _stat and then stat again.

There are a few ways to do this in Windows. My personal preference is to use something like:

char strBuffer[1024];

FILE *fp = fopen (file,"rb");  // Binary read mode
while (!feof (fp))
   fread (strBuffer,1,sizeof (strBuffer),fp);

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