Читать два файла одновременно построчно

Я хотел бы прочитать два 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 и так далее.

Обновить

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

0

Решение

Хотя было бы легче сказать, какой именно разбор вам нужен, имея отрывок из файла. Я просто пошел и скачал этот файл Homo_sapiens.GRCh38.dna.chromosome.22.fa который отформатирован следующим образом:

22 днк: хромосома хромосома: 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;
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector