【发布时间】:2013-11-29 16:38:52
【问题描述】:
我构造了一个用于处理某个文件形式的类,它的构造函数遍历文件并搜索我需要的关键信息 - 想法是字符写在多行上,我想读取每个文件的第一个字符行,每行的第二个字符,依此类推。
我有下面的构造函数和定义(可能很可怕——这是我第一次用 C++ 写任何严肃的东西),
class AlignmentStream{
private:
const char* FileName;
std::ifstream FileStream;
std::vector<int> NamesStart;
std::vector<int> SequencesStart;
std::vector<int> SequenceLengths;
int CurrentPosition;
int SequenceNum;
public:
AlignmentStream(const char* Filename);
std::vector<int> tellSeqBegins();
std::vector<int> tellNamesStart();
std::vector<int> tellSequenceLengths();
int getSequenceNum();
AlignedPosition get();
};
AlignmentStream::AlignmentStream(const char* Filename)
{
FileName = Filename;
FileStream.open(FileName);
std::cout << "Filestream is open: " << FileStream.is_open() << std::endl;
std::cout << "Profiling the alignment file..." << std::endl;
if (FileStream.is_open() == false)
throw StreamClosed(); // Make sure the stream is indeed open else throw an exception.
if (FileStream.eof())
throw FileEnd();
char currentchar;
// Let's check that the file starts out in the correct fasta format.
currentchar = FileStream.get();
if (FileStream.eof())
throw FileEnd();
if (currentchar != '>')
throw FormatError();
NamesStart.push_back(FileStream.tellg());
bool inName = true;
bool inSeq = false;
int currentLength = 0;
while(!FileStream.eof()){
while (!FileStream.eof() && inName == true) {
if (currentchar == '\n') {
inName = false;
inSeq = true;
SequencesStart.push_back(FileStream.tellg());
} else {
currentchar = FileStream.get();
}
}
while (!FileStream.eof() && inSeq == true) {
if (currentchar == '>') {
inName = true;
inSeq = false;
NamesStart.push_back(FileStream.tellg());
} else {
if (currentchar != '\n') {
currentLength++;
}
currentchar = FileStream.get();
}
}
SequenceLengths.push_back(currentLength); // Sequence lengths is built up here - (answer to comment)
currentLength = 0;
}
SequenceNum = (int)SequencesStart.size();
// Now let's make sure all the sequence lengths are the same.
std::sort(SequenceLengths.begin(), SequenceLengths.end());
//Establish an iterator.
std::vector<int>::iterator it;
//Use unique algorithm to get the unique values.
it = std::unique(SequenceLengths.begin(), SequenceLengths.end());
SequenceLengths.resize(std::distance(SequenceLengths.begin(),it));
if (SequenceLengths.size() > 1) {
throw FormatError();
}
std::cout << "All sequences are of the same length - good!" << std::endl;
CurrentPosition = 1;
FileStream.close();
}
抱歉,它是一个相当大的块,无论如何构造函数逐个字符地遍历并获取要读取的每一行的起点。 get 函数(未显示)然后通过并寻找每一行的开头 + 还要多少才能到达正确的字符 - 由成员变量 CurrentPos 给出。然后它构造我的另一个名为 AlignedPosition 的自定义对象并返回它。
AlignedPosition AlignmentStream::get()
{
std::vector<char> bases;
for (std::vector<int>::iterator i = SequencesStart.begin(); i != SequencesStart.end(); i++) {
// cout messages are for debugging purposes.
std::cout << "The current filestream position is " << FileStream.tellg() << std::endl;
std::cout << "The start of the sequence is " << *i << std::endl;
std::cout << "The position is " << CurrentPosition << std::endl;
FileStream.seekg((int)(*i) + (CurrentPosition - 1) );
std::cout << "The Filestream has been moved to " << FileStream.tellg() << std::endl;
bases.push_back(FileStream.get());
}
CurrentPosition++;
//this for loop is just to print the chars read in for debugging purposes.
for (std::vector<char>::iterator i = bases.begin(); i != bases.end(); i++) {
std::cout << *i << std::endl;
}
return AlignedPosition(CurrentPosition, bases);
}
如您所见,第一个循环遍历每行的起始位置 + CurrentPosition,然后获取 char 并将其推回向量上,该向量被传递给我的 AlignedPosition 构造函数,其他所有内容都是用于调试的消息。但是在执行时我看到了这个:
eduroam-180-37:libHybRIDS wardb$ ./a.out
Filestream is open: 1
Profiling the alignment file...
All sequences are of the same length - good!
SeqNum: 3
Let's try getting an aligned position
The current filestream position is -1
The start of the sequence is 6
The position is 1
The Filestream has been moved to -1
The current filestream position is -1
The start of the sequence is 398521
The position is 1
The Filestream has been moved to -1
The current filestream position is -1
The start of the sequence is 797036
The position is 1
The Filestream has been moved to -1
?
?
?
Error, an invalid character was present
Couldn't get the base, caught a format error!
简而言之,我看到的是文件流位置是-1,并且在使用搜索时不会改变。这会导致无效字符和在我的 AlignedPosition 构造函数中抛出异常。这与已经在我的构造函数中浏览文件直到结束有关吗?为什么我在输入流中的位置一直保持在-1?
谢谢, 本。
【问题讨论】:
-
如果您在流中获得文件结尾,
seekg可能不会清除它。您需要先在流上调用clear()。由于您阅读到 EOF,您可能需要致电clear。 (参考:en.wikipedia.org/wiki/Seekg) -
谢谢,我希望基本上清楚我要完成的工作,输入文件有一系列字符串,我首先在构造函数中找到每个字符串的起始位置一个(它们包含以“>”开头的一行,然后是一个名称,然后下面的行是实际的字符串)。因此,当我调用 get 时,它应该获取每个序列的第一个字符(也就是第一个位置),然后当我第二次调用 get() 时 - 每个序列的第二个字符,依此类推。
-
您好,您的 clear() 建议有效!如果您将其作为答案,我将投票并将其设置为答案。
-
PS 如果有人知道我是如何在文件中移动的,或者如果我有更简单的方法来做我正在做的事情,我很高兴听到 - 这是我的第一次尝试以任何严肃的方式处理文件流,而不仅仅是在 Hello World 中阅读!
-
完成!至于做你正在做的事情更容易或更有效:如果你有足够的内存,那么我要做的就是将数据读入内存,可能将其存储在
vectors 或arrays 中。由于所有记录都应该具有相同的大小,因此您知道在第一条记录之后它们应该是什么大小,这简化了事情。这意味着您可以立即检测到错误,而不是在最后检测到错误,它还可以用于简化您的读入代码以读取固定长度的记录,只需验证换行符和>是否在您期望的位置。
标签: c++ constructor character seekg