问题描述
我有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 characters0x0D 0x0A
), it works (lineStr == line2Str
). - If
buglines.txt
was created under Linux (hexadecimal editor shows line separators as 1 character0x0A
), 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下创建的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!