2012-03-25 4 views
3

Ich frage mich, ob dies der beste Weg ist, um über mein Problem zu lösen.Gehe zu einem bestimmten Punkt einer Binärdatei in C (mit fseek) und dann von diesem Ort (mit fread) lesen

Ich kenne die Werte für bestimmte Offsets einer Binärdatei, wo die Informationen, die ich will, gehalten wird ... Was ich tun möchte, ist zu den Offsets zu springen und dann eine bestimmte Menge an Bytes von diesem Ort aus zu lesen.

Nach der Verwendung von Google, bin ich zu der Schlussfolgerung gekommen, dass meine beste Wette ist, fseek() zu verwenden, um die Position des Offsets zu verschieben, und fread() zu verwenden, um eine Anzahl von Bytes von dieser Position zu lesen.

Bin ich richtig, wenn ich das denke? Und wenn ja, wie geht das am besten? d. h. wie man die zwei zusammenbringt.

Wenn ich nicht richtig bin, was würden Sie vorschlagen, dass ich stattdessen tun?

Vielen Dank im Voraus für Ihre Hilfe.

Matt

bearbeiten:

folgte ich ein Tutorial über fread() und an folgende angepasst:

`#include <stdio.h> 
    int main() 
    { 
     FILE *f; 
     char buffer[11]; 
     if (f = fopen("comm_array2.img", "rt")) 
     { 
     fread(buffer, 1, 10, f); 
     buffer[10] = 0; 
     fclose(f); 
     printf("first 10 characters of the file:\n%s\n", buffer); 
     } 
     return 0; 
    }` 

So habe ich die Datei 'comm_array2.img' und lese die ersten 10 Zeichen aus der Datei.

Aber von dem, was ich davon verstehen, das geht vom Start-of-Datei, mag ich von einem Platz-in-Datei gehen (Offset)

Ist das mehr Sinn machen?

bearbeiten Nummer 2:

Es scheint, dass ich ein bisschen dunkel wurde, und alles, was benötigt wird (es wäre von meinem Versuch scheint) ist die fseek zu setzen() vor dem fread(), die ich habe in dem Code oben, und es sucht nach diesem Ort und liest dann von dort.

+2

Ja. Verwenden Sie fseek() und fread(). Welchen Code hast du ausprobiert? – erisco

+1

Ja, du hast Recht, aber was ist deine Frage oder dein Problem? –

+0

Es gibt Tutorials im Internet, die zeigen, wie man sie benutzt. Mit den Suchbegriffen "fseek fread C tutorial" sollte es einfach sein, einige zu finden. Hast du irgendwas durchgearbeitet? – gbulmer

Antwort

2

Wenn Sie Dateiströme anstelle von Dateideskriptoren verwenden, können Sie sich eine (einfache) Funktion analog zum Systemaufruf POSIX pread() schreiben.

Sie können es problemlos mit Streams anstelle von Dateideskriptoren emulieren. Vielleicht sollten Sie sich eine Funktion wie diese schreiben (was eine etwas andere Schnittstelle von der einen habe ich in einem Kommentar vorgeschlagen):

size_t fpread(void *buffer, size_t size, size_t mitems, size_t offset, FILE *fp) 
{ 
    if (fseek(fp, offset, SEEK_SET) != 0) 
     return 0; 
    return fread(buffer, size, nitems, fp); 
} 

Dies ist ein vernünftiger Kompromiss zwischen den Konventionen der pread() und fread().


Was die Syntax der Funktionsaufruf aussehen würde? Zum Beispiel Lesen von dem Offset 732 und dann wieder von Offset 432 (beide vom Anfang der Datei) und Filestream f genannt.

Da Sie nicht gesagt haben, wie viele Bytes zu lesen sind, nehme ich jedesmal 100 an. Ich nehme an, dass die Zielvariablen (Puffer) buffer1 und buffer2 sind, und dass sie beide groß genug sind.

if (fpread(buffer1, 100, 1, 732, f) != 1) 
    ...error reading at offset 732... 
if (fpread(buffer2, 100, 1, 432, f) != 1) 
    ...error reading at offset 432... 

Der Rückgabewert ist die Anzahl der vollständigen Einheiten von jeweils 100 Byte. entweder 1 (hat alles) oder 0 (etwas ist schief gelaufen).

Es gibt andere Möglichkeiten, diesen Code zu schreiben:

if (fpread(buffer1, sizeof(char), 100, 732, f) != 100) 
    ...error reading at offset 732... 
if (fpread(buffer2, sizeof(char), 100, 432, f) != 100) 
    ...error reading at offset 432... 

Dieses liest 100 einzelne Bytes jedes Mal; Der Test stellt sicher, dass Sie alle 100 wie erwartet erhalten. Wenn Sie den Rückgabewert in diesem zweiten Beispiel erfassen, können Sie wissen, wie viele Daten Sie erhalten haben. Es wäre sehr überraschend, wenn der erste Lesevorgang erfolgreich wäre und der zweite fehlgeschlagen wäre; ein anderes Programm (oder ein Thread) hätte die Datei zwischen den beiden Aufrufen an fpread() abschneiden müssen, aber es ist bekannt, dass noch mehr lustige Dinge passieren.


Die Emulation wird nicht perfekt sein; Der Aufruf pread() bietet eine garantierte Atomarität, die die Kombination fseek() und fread() nicht bietet. Aber das wird in der Praxis selten ein Problem sein, es sei denn, Sie haben mehrere Prozesse oder Threads, die gleichzeitig die Datei aktualisieren, während Sie versuchen, sie zu positionieren und zu lesen.

+0

Vielen Dank dafür, ich wollte dich bitten, in deinen Kommentar ein wenig weiter zu gehen und du hast mich vorweggenommen, also danke. Also, wenn ich dieses Recht verstehe, würde ich diese Funktion erstellen, und verwenden Sie es in der gleichen war, wie ich ursprünglich pread verwendet hätte und übergeben Sie den Dateinamen (anstelle von Dateideskriptor) und Offset? – user1291631

+0

Sortierung ... Ihr Kommentar erwähnt den Dateinamen, aber weder 'fread()' noch 'fseek()' funktionieren mit Dateinamen; das ist 'fopen()' 's Job. Die 'fpread()' Funktion ist ein fast drop-in Ersatz für die 'fseek()' und 'fread()' Aufrufe. Wenn Sie möchten, dass ein Dateiname verwendet wird, müssen Sie 'fopen()' und (vermutlich) 'fclose()' die Datei in der Funktion angeben und den 'fp'-Parameter nicht übergeben. Sie würden wahrscheinlich den Dateinamen als erstes Argument setzen. Sie würden "" rb "' verwenden, um die Binärdatei zum Lesen zu öffnen; Es spielt keine Rolle, ob das b unter Unix steht, aber auf anderen Plattformen tut es das. –

+0

Ah ja, meine Entschuldigung, ich wollte sagen übergeben, was wäre 'fp' (dh was normalerweise zurückgegeben wird, wenn Sie fopen() verwenden, wie ich es verstehe) Allerdings, aus Ihrem Kommentar sehe ich, dass ich tatsächlich nicht bestehen 'fp' Parameter? – user1291631

0

Ihre Theorie klingt korrekt. Öffnen, suchen, lesen, schließen.

Erstellen Sie eine Struktur für die Daten, die Sie lesen möchten, und übergeben Sie einen Zeiger auf read() des zugeordneten Speichers der Struktur. Sie werden wahrscheinlich #pragma pack (1) oder ähnliches in der Struktur benötigen, um Fehlausrichtungsprobleme zu vermeiden.

1

Es hängt oft von der Entfernung zwischen den Teilen ab, die Ihnen wichtig sind. Wenn Sie nur ein paar Bytes zwischen den Teilen überspringen oder ignorieren, die Ihnen wichtig sind, ist es oft einfacher, diese Daten zu lesen und zu ignorieren, was Sie gelesen haben, anstatt fseek zu verwenden, um darüber zu springen. Eine typische Methode hierfür ist, eine Struktur zu definieren, die sowohl die Daten enthält, die Sie interessieren, als auch Platzhalter für diejenigen, die Sie nicht interessieren, in der Struktur lesen und dann nur die Teile verwenden, die Ihnen wichtig sind:

struct whatever { 
    long a; 
    long ignore; 
    short b; 
} w; 

fread(&w, 1, sizeof(w), some_file); 

// use 'w.a' and 'w.b' here. 

Wenn es einen großen Abstand zwischen den Teilen gibt, die Ihnen wichtig sind, besteht die Möglichkeit, dass Ihre ursprüngliche Idee, fseek zu verwenden, um die wichtigen Teile zu erhalten, einfacher ist.

Verwandte Themen