2015-04-23 2 views
1

Следующий код работает, но примерно в два раза неэффективен по сравнению с тем, когда я использую (linux) трубу, которая дает распакованные данные для (модифицированной) программы. Мне нужен постоянный поток внутри программы, который я могу продолжать раскалывать на \n. Есть ли способ сделать это, используя поток (string?) Или любой другой трюк?Как реализовать поток, который может быть разделен символом новой строки

int main(int argc, char *argv[]) { 
static const int unzipBufferSize = 8192; 
long long int counter = 0; 
int i = 0, p = 0, n = 0; 
int offset = 0; 
char *end = NULL; 
char *begin = NULL; 
unsigned char unzipBuffer[unzipBufferSize]; 
unsigned int unzippedBytes; 
char * inFileName = argv[1]; 
char buffer[200]; 
buffer[0] = '\0'; 
bool breaker = false; 
char pch[4][200]; 
Read *aRead = new Read; 
gzFile inFileZ; 
inFileZ = gzopen(inFileName, "rb"); 
while (true) { 
    unzippedBytes = gzread(inFileZ, unzipBuffer, unzipBufferSize); 
    if (unzippedBytes > 0) { 
     unzipBuffer[unzippedBytes] = '\0'; //put a 0-char after the total buffer 
     begin = (char*) &unzipBuffer[0]; // point to the address of the first char 
     do { 
      end = strchr(begin,(int)'\n'); //find the end of line 
      if (end != NULL) *(end) = '\0'; // put 0-char to use it as a c-string 
      pch[p][0] = '\0'; \\ put a 0-char to be able to strcat 
      if (strlen(buffer) > 0) { // if buffer from previous iteration contains something 
       strcat(pch[p], buffer); // cat it to the p-th pch 
       buffer[0] = '\0'; \\ set buffer to null-string or "" 
      } 
      strcat(pch[p], begin); // put begin (or rest of line in case there was a buffer into p-th pch 

      if (end != NULL) { // see if it already points to something 
       begin = end+1; // if so, advance begin to old end+1 
       p++; 
      } 

      if(p>3) { // a 'read' contains 4 lines, so if p>3 
       strcat(aRead->bases,pch[1]); // we use line 2 and 4 as 
       strcat(aRead->scores,pch[3]); // bases and scores 
       //do things with the reads 
       aRead->bases[0] = '\0'; //put them back to 0-char 
       aRead->scores[0] = '\0'; 
       p = 0; // start counting next 4 lines 
      } 

     } 
     while (end != NULL); 
     strcat(buffer,pch[p]); //move the left-over of unzipBuffer to buffer 
    } 
    else { 
     break; // when no unzippedBytes, exit the loop 
    } 
} 
+1

Почему бы не использовать, например. [Библиотека Boost iostreams] (http://www.boost.org/doc/libs/1_58_0/libs/iostreams/doc/index.html), которые имеют классы для gzipped-файлов. Затем вы можете использовать обычную 'std :: getline' для чтения по строковой основе. –

+0

Цель этой программы - быть как можно быстрее. Я ошибаюсь, полагая, что использование библиотеки C++, такой как Boost, будет не таким быстрым, как если бы мы сохранили это на C, используя c-строки? – Niels

+0

Также мне очень интересно, как это можно сделать самым простым способом, без использования внешних библиотек. Одной из целей zlib должно быть прямое использование данных, которые извлекаются, не так ли? Без необходимости использования других библиотек ... – Niels

ответ

0

Ваша основная проблема, вероятно, в стандартной библиотеке строк C.

С помощью strxxx() funcions, вы перебор полного буфера нескольких раз каждого вызова, первый для strchr(), то для strlen(), то для каждого из strcat() вызовов. Использование стандартной библиотеки - хорошая вещь, но здесь она просто неэффективна.

Попробуйте, если вы могли бы придумать что-нибудь попроще, которая касается каждого символа только один раз, как (код, чтобы показать принцип, не ожидаем, что он работает):

do 
{ 
    do 
    { 
     *tp++ = *sp++; 
    } while (sp < buffer_end && *sp != '\n'); 

    /* new line, do whatever it requires */ 
    ... 
    /* reset tp to beginning of buffer */ 
} while (sp < buffer_end); 
+0

Четыре строки «чтения» собрались вместе. Разве это не слишком упрощенно? – Niels

+0

И в какой момент я должен получить новый unzipBuffer из gzread здесь? Что я должен представлять себе tp и sp? – Niels

+1

Я просто хотел показать вам принцип (коснитесь каждого элемента массива только один раз) вместо выполнения вашей работы;) – mfro

0

Я пытаюсь получить эту работу , но все, что он делает, дает ошибку сегментации во время выполнения:

do { 
    unzippedBytes = gzread(inFileZ, unzipBuffer, unzipBufferSize); 
    if (unzippedBytes > 0) { 

     while (*unzipBuffer < unzippedBytes) { 
      *pch = *unzipBuffer++; 
      cout << pch; 

      i++; 
     } 
     i=0; 
    } 
    else break; 
} while (true); 

Что я здесь делаю неправильно?

Смежные вопросы