我有一个包含标题和非常长字符串的文件,如:
>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
全部谢谢。
答案 0 :(得分:3)
有几位候选人:
补充阅读:
<强> 编辑: 强>
如果对编码有疑问,您可以在文件的开头和结尾显示字节的二进制值(十六进制):
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:文本流是由行组成的有序字符序列,每行由零个或多个字符组成 加上一个终止的换行符。 最后一行是否需要 终止的换行符是实现定义的。人物 可能必须在输入和输出上添加,更改或删除 符合在主机中表示文本的不同约定 环境即可。因此,不需要一对一的对应关系 流中的字符与外部字符之间 表示。从文本流中读取的数据必然是 比较等于先前写入该流的数据 仅在以下情况下:数据仅包含打印字符和控件 字符水平制表符和换行符;没有换行符 紧接着前面有空格字符;最后一个角色是 换行符。是否写出空格字符 在读入时出现换行符之前 实现定义的。