2016-07-18 4 views
0

Wie readline() Funktion. Ich dachte, dies zu implementieren,So implementieren Sie die Lesedatei Zeile für Zeile wie z. B. readline()

zuerst muss ich Datei wie read(fd, buf, 4096); lesen, und dann muss ich buf[i] byteweise wie if (buf[i] == '\n') vergleichen.

Also, wenn ich entsprechende i finden, dann verwenden Sie lseek(), um erste Datei Offset gehen, und dann wieder read(fd, buf, i). Nach einer solchen Operation führt der zweite Aufruf diesen Mechanismus erneut aus.

Ich dachte zuerst diese Lösung, aber Vergleich buf[i], was Byte für Byte vergleichen bedeutet, ist zu langsam, um alle Zeichen in fd zu lesen. Muss ich so vergleichen oder gibt es bessere Lösungen?

+4

Warum nicht fget/fgets verwenden? – inzanez

+0

Es wird Zeile für Zeile gelesen. Aber ich möchte die Lösung mit read() kennenlernen. Weil fgets oder andere Standard-E/A-Funktionen schließlich read(), write() Systemaufrufe verwenden. – allen

+3

Nur eine Idee: Sie könnten den 'readline' Quellcode durchsuchen, um zu sehen, wie es geht. – Siguza

Antwort

-2

Implementieren Sie fgetc mit einem 'lesen' für 1 Zeichen, verwenden Sie Ihr eigenes getc, um readline zu implementieren?

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 

char my_getc() 
{ 
    unsigned char ch[1]; 

    read(1, ch, 1); 

    return ch[0]; 

} 

char *my_readline() 
{ 
     char line[4096]; 
     char *ret; 
     char c; 
     int position = 0; 

     while(c = my_getc() != '\n') 
       line[position++] += c; 

     line[position] = '\0'; 

     ret = malloc(sizeof(char) * strlen(line)); 


     return ret; 
} 



int main(int argc, char *argv[]) 
{ 
     char c; 

     printf("%s\n", my_readline()); 

} 

Wenn Sie eine gut getestete Lösung benötigen Sie vielleicht die Quelle einer bestehenden Implementierung lesen sollte, ...

+0

1) Der Inhalt von 'ret []' wird nie gesetzt - Code funktioniert nicht 2) Kein Schutz gegen Pufferüberlauf, 3) Keine 'EOF' Erkennung. 4) Zugewiesener Puffer ist nicht frei. – chux

3

Ich bin der Annahme, dass der Grund, warum Sie nicht fgets() ist verwenden können, dass dies eine Übung ist in was Sie etwas über POSIX Low-Level-I/O-Funktionen lernen sollten, und vielleicht ein bisschen über Pufferung. Wenn Sie wirklich nur darauf bedacht sind, die Daten zu erhalten, dann fordere ich Sie auf, einen Stream um Ihren Dateideskriptor über fdopen() zu schreiben und dann fgets() zu verwenden, um es zu lesen.

Ich dachte zuerst diese Lösung, aber das Vergleichen von buf [i], was bedeutet Byte für Byte vergleichen, ist zu langsam, um alle Zeichen in der fd zu lesen. Muss ich so vergleichen oder gibt es bessere Lösungen?

Sie möchten bis zum ersten Auftreten eines gegebenen Bytes lesen. Wie können Sie das tun, ohne jedes gelesene Byte zu untersuchen? Es ist nicht möglich, außer vielleicht mit Hardware-Unterstützung, und Sie werden das wahrscheinlich nicht haben.

Ich denke, Ihr Anliegen ist sowieso deplaziert. Es ist viel kostspieliger, Daten von der Festplatte in den Speicher zu verschieben, als die Daten im Speicher danach zu untersuchen. Wenn Sie auf der von Ihnen vorgeschlagenen niedrigen Stufe arbeiten und eine gute Leistung wünschen, müssen Sie die Daten in ausreichend großen Blöcken von der Festplatte lesen, wie Sie es in Ihrem read()-basierten Ansatz sehen.

Auf der anderen Seite folgt, dass Sie auch Re-Lektüre keine Daten vermeiden möchten, wenn Sie also nach der guten Leistung sind, dann ist die lseek() ungeeignet. Darüber hinaus, wenn Sie nicht suchbare Dateien wie Pipes behandeln müssen, ist lseek() völlig außer Frage. In beiden Fällen müssen Sie den Puffer irgendwie pflegen und bereit sein, mehrere Anfragen von seinem Inhalt zu bedienen. Außerdem müssen Sie auf die Wahrscheinlichkeit vorbereitet sein, dass die Zeilengrenzen nicht mit der Puffergrenze übereinstimmen, dass Sie manchmal mehr als einen Lesevorgang benötigen, um eine neue Zeile zu finden, und dass Zeilen auch länger als Ihr Puffer sind das ist.

Wenn also fgets() und andere Stream-basierte I/O-Alternativen keine Option für Sie sind, dann haben Sie ein Pufferverwaltungsproblem zu lösen. Ich schlage vor, dass du dort anfängst. Sobald Sie das geschafft haben, sollte es einfach sein, ein Analogon von fgets() in Bezug auf diese Pufferung zu schreiben.

Verwandte Themen