在Windows下使用fstream :: seekg在Unix下创建的文件 [英] Using fstream::seekg under windows on a file created under Unix

查看:137
本文介绍了在Windows下使用fstream :: seekg在Unix下创建的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有C ++一个跨平台程序(在Linux下使用g ++编译,在PC下使用Visual Studio编译)。此程序将行写入文本文件(使用< 运算符和 std :: endl ),从生成的文本文件中读取数据(使用 std :: getline )。

I have C++ a cross-platform program (compiled with g++ under Linux and with Visual Studio under PC). This program writes lines to a text file (using << operator and std::endl) but can also read data back from the generated text file (using std::getline).

内存,当读取数据文件,我第一次读它,并保存在我的程序中的数据位置。当需要数据时,我稍后使用 seekg 移动到特定位置并读取数据。

To optimize data access and save memory, when reading the data file, I read it a first time and save data position in my program. When data is needed, I later use seekg to move to a specific position and read the data.


  • 在PC上创建和阅读文件很好。

  • 在Linux上创建和阅读文件工作正常。


在PC下,seekg有时无法移动光标。我可以隔离在下面的例子中的问题。它读取文件一次,保存第二个分区和值,然后返回到保存的位置并再次读取该行。

Under PC, seekg sometime fails to move the cursor accordingly. I could isolate the problem in the example below. It reads the file once, saves second lineposition and value, then moves back to the saved position and reads the line again.

#include <fstream>
#include <iostream>
#include <string>
#include <assert.h>
int main()
{
    std::fstream file;
    file.open( "buglines.txt", std::ios_base::in );
    if ( file.is_open() )
    {
        std::streampos posLine2;
        std::string lineStr;
        std::string line2Str;
        int line = 1;
        while ( std::getline( file, lineStr ) )
        {
            if ( line == 1 )
                posLine2 = file.tellg(); // save line 2 position
            if ( line == 2 )
                line2Str = lineStr; // save line 2 content

            ++line;
            std::cout << lineStr <<std::endl;
        }
        std::cout << "Reached EOF, trying to read line 2 a second time" << std::endl;
        file.clear(); // clear EOF flag
        file.seekg(posLine2); // move to line 2
        std::getline( file, lineStr ); // read the line
        assert( lineStr == line2Str ); // compare

    }
    return 0;
}

我从Windows运行。

I'm running this from Windows.


  • 如果在Windows下创建了 buglines.txt (十六进制编辑器显示行分隔符为2个字符 0x0D 0x0A ),它工作( lineStr == line2Str )。

  • 如果 buglines.txt 是在Linux下创建的(十六进制编辑器将行分隔符显示为1个字符 0x0A ),它不工作(lineStr是空字符串) 。

  • If buglines.txt was created under Windows (hexadecimal editor shows line separators as 2 characters 0x0D 0x0A), it works (lineStr == line2Str).
  • If buglines.txt was created under Linux (hexadecimal editor shows line separators as 1 character 0x0A), it does not works (lineStr is empty string). Even if the getline loop worked perfectly.

我知道两个系统的处理方式与EOL不同,但是我只是使用 getline 阅读功能,我希望它会巧妙地工作...我错过了什么?

I know both system deals differently with EOL, but as I'm just using getline function for reading, I was hoping that it would smartly work...am I missing something?

推荐答案

我无法轻易升级我的项目的运行时库,显然没有其他的解决方案。

I can't easily upgrade the runtime library for my project and as, apparently, there is no other "solution".

std :: ios_base :: binary 属性。它修复了报告的问题,但引入了一个新的:当使用 getline 读取文件时,我们获得额外的 \r

I tried to set std::ios_base::binary attribute upon file open. It fixes the reported problem but introduces a new one: We get extra \r chacters when reading the file with getline.

所以如果任何人有相同的问题,需要一个修复,这里是一个解决方法:只需关闭文件,重新打开它,然后吃前n个字符将读指针移动到正确的位置:

So if anyone has the same problem and needs a fix, here is a workaround: simply close the file, re-open it, and then eat the first n characters to move the read pointer to the good location:

#include <fstream>
#include <iostream>
#include <string>
#include <assert.h>

int main()
{
    std::fstream file;
    const std::string fileName = "buglines.txt";
    file.open( fileName.c_str(), std::ios_base::in );
    if ( file.is_open() )
    {
        std::streampos posLine2;
        std::string lineStr;
        std::string line2Str;
        int line = 1;
        while ( std::getline( file, lineStr ) )
        {
            if ( line == 1 )
                posLine2 = file.tellg(); // save line 2 position
            if ( line == 2 )
                line2Str = lineStr; // save line 2 content

            ++line;
            std::cout << lineStr << std::endl;
        }
        std::cout << "Reached EOF, trying to read line 2 a second time" << std::endl;
        //file.clear(); // clear EOF flag
        //file.seekg(posLine2); // move to line 2
        file.close();
        file.open( fileName.c_str(), std::ios_base::in );
        assert( file.is_open() );
        char* temp = new char[static_cast<int>(posLine2)+1];
        file.read( temp, static_cast<int>(posLine2)+1 ); // if posLine2 is too big, consider splitting with in a loop
        delete [] temp;
        assert( file.tellg() == posLine2 );

        std::getline( file, lineStr ); // read the line
        assert( lineStr == line2Str ); // compare
    }
    return 0;
}

这篇关于在Windows下使用fstream :: seekg在Unix下创建的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆