逐行同时读取两个文件

时间:2017-05-01 09:58:44

标签: c++ fasta

我想逐行同时阅读两个FASTA个文件。我有以下代码逐行读取一个文件。

#include <iostream>
#include <fstream>

int main( int argc, char **argv ){
    if( argc <= 1 ){
        std::cerr << "Usage: "<<argv[0]<<" [infile]" << std::endl;
        return -1;
    }

    std::ifstream input(argv[1]);
    if(!input.good()){
        std::cerr << "Error opening '"<<argv[1]<<"'. Bailing out." << std::endl;
        return -1;
    }

    std::string line, name, content;
    while( std::getline( input, line ).good() ){
        if( line.empty() || line[0] == '>' || line[0] == '@' ){ // Identifier marker
            if( !name.empty() ){ // Print out what we read from the last entry
                std::cout << name << " : " << content << std::endl;
                name.clear();
            }
            if( !line.empty() ){
                name = line.substr(1);
            }
            content.clear();
        } else if( !name.empty() ){
            if( line.find(' ') != std::string::npos ){ // Invalid sequence--no spaces allowed
                name.clear();
                content.clear();
            } else {
                content += line;
            }
        }
    }
    if( !name.empty() ){ // Print out what we read from the last entry
        std::cout << name << " : " << content << std::endl;
    }

    return 0;
}

但是,我想为多个文件执行此操作。 E,g我有两个文件,file1和file2。执行以下操作。

read file1 line
do some operation
read file2 line
do some operation
repeat till file 1 and file 2 finishes

注意:我不想一次读取file1的所有行,然后读取file2的所有行。我想要一行来自file1,一行来自file2,第二行来自file1,第二行来自file2,依此类推。

更新

文件1

@r0/1
TATTCTTCCGCATCCTTCATACTCCTGCCGGTCAG
AAA
+
EDCCCBAAAA@@@@?>===<;;9:99987776554678
@r1/1
TGATAGATCTCTTTTTTCGCGCCGACATCTACGCC
+
EDCCCBAAAA@@@@?>===<;;9:99987776554
@r2/1
CACGCCCTTTGTAAGTGGACATCACGCCCTGAGCG
+
EDCCCBAAAA@@@@?>===<;;9:99987776554

file2的

@r0/2
GAATACTGGCGGATTACCGGGGAAGCTGGAGC
+
EDCCCBAAAA@@@@?>===<;;9:99987776
@r1/2
AATGTGAAAACGCCATCGATGGAACAGGCAAT
+
EDCCCBAAAA@@@@?>===<;;9:99987776
@r2/2
AACGCGCGTTATCGTGCCGGTCCATTACGCGG
+
EDCCCBAAAA@@@@?>===<;;9:99987776

其实我尝过类似

的东西
std::ifstream input(argv[1]);
std::ifstream input1(argv[2]);
std::string line, name, content;
std::string line1, name1, content1;
    while( std::getline( input, line ).good() && std::getline( input1, line1 ).good() ){

//file1 line operation
// file2 line operation
}

但如果线条不同,这不会起作用。阅读后的行看起来像

@r0/1 TATTCTTCCGCATCCTTCATACTCCTGCCGGTCAGAAA+EDCCCBAAAA@@@@?>===<;;9:99987776554678

1 个答案:

答案 0 :(得分:1)

虽然通过摘录文件可以更容易地判断出您需要什么样的解析。我刚刚下载了这个文件Homo_sapiens.GRCh38.dna.chromosome.22.fa,其格式如下:

  

22 dna:染色体染色体:GRCh38:22:1:50818468:1 REF   NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN   CTGGTCTTGAACTCCTGACCTCAAGTGATCTGCCCACCTCCGCCTCCCAAACTGCTAGAA   TTACAGGCGTGAGCAACCACTCCCTACCTTCCCCCATTTTTATAATAAACATTCTACACA   GGGCTCCTGCCAGCCCTCCAAGCTTCTCACTTTGAGAAGCACAGTCCGCTCTGTCAGACT

由于第一行是文件唯一的,并且没有出现两次,我只是将其删除,而不是为编写解析它的代码而负担自己。但是,如果您的项目需要它存在,我将包含一个功能来完成它。
所以,你需要的第一件事就是从文件中读取。由于我们知道条目是统一的,因此我们可以在不使用getLine();或任何花哨的情况下四处走动。根据您的期望,有两种方法可以实现。
第一种方法,如果您需要从两个文件中读取,直到其中一个文件到达结束:

void readLine(string path1, string path2){
    ifstream inOne(path1);
    ifstream inTwo(path2);  

    while( !inOne.eof() & !inTwo.eof() ){
        string strOne, strTwo;

        inOne>>strOne;  
        inTwo>>strTwo;

        cout<<"1 "<<strOne<<endl;
        cout<<"2 "<<strTwo<<endl;
    }
}

但是,如果您需要继续读取其中一个文件,请使用以下内容:

    while( !inOne.eof() | !inTwo.eof() ){
        string strOne, strTwo;

        if(!inOne.eof())
            inOne>>strOne;  
        if(!inTwo.eof())
            inTwo>>strTwo;

        cout<<"1 "<<strOne<<endl;
        cout<<"2 "<<strTwo<<endl;
    }

现在,至于你想在每一行上执行的实际格式,你很可能注意到我没有写任何东西来处理它。那是因为在我看来,最好的方法就是编写另一个能够做到这一点的功能。你可以称之为formatLine(string line);。然后使用我提供的代码,添加对该函数的调用并相应地修改输出。我无法告诉你究竟是什么样的,因为你可以定义formatLine();来返回从行中提取的元素数组,或者你可以返回vector这总是一个好主意,如果元素数量可能有所不同
现在对于第一行,您可以创建一个仅用于读取该行的函数,因为它非常不同并且可能需要不同的格式。

void readFirst(string path){

    ifstream inOne(path, ios::in | ios::binary); //ORed bitfield to get unformatted binary
    char ch=0;

    while(ch != '\n'){
        inOne.get(ch);
        cout<<ch<<endl;

    }

}

然后,您可能希望将每个字符存储在c字符串中,或​​者附加常规字符串。另外,请不要忘记在使用inOne.close();完成后关闭每个流 的 UPD。
只要行中没有空格,您仍然可以将此代码用于您提供的文件,因为提取器iostream会将它们视为分隔符,因此将其视为新行。
但是,如果您需要确保分隔符不会影响有序提取,请使用我包含的最后一段代码。 ios::binary会阻止格式化,因此您不会丢失任何字符,并且您将能够确切地知道何时移动到新行。它可能看起来像:

void readLine(string path1, string path2){
    ifstream inOne(path1, ios::in | ios::binary);
    ifstream inTwo(path2, ios::in | ios::binary);   

    while( !inOne.eof() | !inTwo.eof() ){
        string strOne, strTwo;

        strOne=readLineBin(inOne);
        strTwo=readLineBin(inTwo);

        cout<<"1 "<<strOne<<endl;
        cout<<"2 "<<strTwo<<endl;
    }
}

string readLineBin(ifstream& in){
    string line="";

    char ch=0;
    while(ch != '\n' & !in.eof()){
        in.get(ch);
        line+=ch;
    }
    return line;
}