Я хотел бы прочитать два 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
Хотя было бы легче сказать, какой именно разбор вам нужен, имея отрывок из файла. Я просто пошел и скачал этот файл 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;
}
Других решений пока нет …