同时逐行阅读两个文件

Read two files simultaneously line by line

本文关键字:两个 文件 逐行      更新时间:2023-10-16

我想同时逐行阅读两个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等。

update

file1

@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

,尽管通过摘录文件来判断您需要哪种样本进行解析会更容易。我刚刚下载了以下格式的文件Homo_sapiens.GRCh38.dna.chromosome.22.fa

22 DNA:染色体染色体:Grch38:22:1:50818468:1 Ref Nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn an, ctggtcttgaactcctgacctcagtgatcccccccccccctcccctcccccaaactgctagaa ttacaggcgcgtgagcaaccactcctccttccccccttttataataaaacattctacaca GGGCTCCTGCCAGCCCTCCAGCTTCTCACTTGAGAAGCAGCAGTCCGCTCTGTGTCAGACT

由于文件独有的第一行,并且不会出现两次,所以我只是将其删除,而不是为了编写用于解析的代码而负担自己的负担。但是,如果您的项目要求它存在,我也将包括一个函数。
因此,您需要的第一件事是实际从文件中读取。由于我们知道条目是统一的,因此我们可以不使用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;
}