如何在不读取整个文件的情况下查找文件中字符串的长度

时间:2016-10-06 18:21:03

标签: c++ file io

我有一个包含标题和非常长字符串的文件,如:

>Ecoli100k
AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGCTTCTGAACTG
GTTACCTGCCGTGAGTAAATTAAAATTTTATTGACTTAGGTCACTAAATACTTTAACCAATATAGGCATAGCGCACAGAC
....

我尝试使用以下方法检索文件大小和标题大小:

ifstream file(fileName.c_str(), ifstream::in | ifstream::binary);

string line1;
getline(file,line1);
int line1Size = line1.size();

file.seekg(0, ios::end);
long long fileSize = file.tellg();
file.close();

例如,对于包含长度为100k且标题为>Ecoli100k的字符串的文件,fileSize为101261且line1Size为10.现在用于计算字符串的长度而不再读取:

101261 - (10 + 1)= 101250表示没有标题,此文件包含101250个字符

101250/81 = 1250这意味着有1250个完整行(但最后一行没有\ n)所以我们必须从101250中减去1249以获得字符串的长度,但这是错误的。我们得到100k + 1而不是100k。

在代码中:

int remainedLineCount = 
        (fileSize - line1Size - 1 - 1 /*the last line has no \n*/)/81 ;
cout<<(fileSize - line1Size - 1 - remainedLineCount )<<"\n";

在另一个例子中,我只添加另一个字符,因为文件中的换行符大小变为101263,再次使用此计算,我们将进入100k + 2而不是100k + 1.

任何人都知道这[[额外1]]来自哪里?文件末尾有什么东西吗?

编辑:

根据要求,这是文件开头和结尾的字节的二进制值(十六进制):

  

偏移0:3e 45 63 6f 6c 69 31 30 30 6b

     

抵消0000018b83:54 47 47 43 41 47 41 41 43 0a

全部谢谢。

1 个答案:

答案 0 :(得分:3)

有几位候选人:

  • 如果你在windows下,如果文件是以文本模式写的,那么第一行+换行将存储在10 + 2个字符中,因为'\ n'被翻译成'\ r'+'' \ n';
  • 再次,如果文件是以文本模式编写的,则可能会添加文件结束字符(在文本模式下不可见),这在二进制模式下可读。
  • 无论是否将'\ n'添加到文件的最后一行(参见我的第二次编辑中的说明),它也是依赖于implmenetation的。

补充阅读:

<强> 编辑:

如果对编码有疑问,您可以在文件的开头和结尾显示字节的二进制值(十六进制):

void show (istream &ifs, int count) {  // utility function
    cout <<"offset "<<setw(10)<<ifs.tellg()<<": ";
    for (int i=0; i<10; i++) 
        cout << setw(2) << setfill('0') <<hex<<ifs.get()<<" ";
    cout <<endl; 
}

// with your newly opened filestream: 
show(ifs, 12);  
ifs.seekg(-10,ios::end);
show(ifs, 10);  

编辑2:

所以看起来你的最后一行末尾有一个换行符(输出中的ASCII码0a结束)。

了解文本模式和二进制模式可能存在差异非常重要。 C ++标准没有详细说明这些,但依赖于C stdio的第27.1.9.4节,它在C11标准中有所描述:

  

7.21.2 / 2:文本流是由行组成的有序字符序列,每行由零个或多个字符组成   加上一个终止的换行符。 最后一行是否需要   终止的换行符是实现定义的。人物   可能必须在输入和输出上添加,更改或删除   符合在主机中表示文本的不同约定   环境即可。因此,不需要一对一的对应关系   流中的字符与外部字符之间   表示。从文本流中读取的数据必然是   比较等于先前写入该流的数据   仅在以下情况下:数据仅包含打印字符和控件   字符水平制表符和换行符;没有换行符   紧接着前面有空格字符;最后一个角色是   换行符。是否写出空格字符   在读入时出现换行符之前   实现定义的。