Dateizeiger verschieben (fread)

OP #6700454
Lesenswert?

Hi,

ich habe versucht den Dateizeiger beim einlesen einer Textdatei mit 
einer Schleife an Newline auszurichten..

Wieso funktioniert das so nicht?
1
#include <stdio.h>
2

3
int main()
4
{
5
 int intsize = 100;
6
 char *buffer[intsize];
7
 buffer[intsize - 1] = '\0';    
8
 FILE *fp = fopen ("list.txt", "r");
9
 int cnt=0;
10
  while (fread (buffer, intsize-1, 1, fp) == 1)
11
    {
12
      printf ("loop %d\n", cnt);
13
      int nlpos = intsize - 1;
14
      while (buffer[nlpos] != '\n')
15
  {
16
    nlpos--;
17
   }
18
  
19
  fseek(fp,nlpos,SEEK_CUR);
20
  buffer[nlpos + 1] = '\0';
21
}
22
}
Moderator Persönliche Seite #6700852
Lesenswert?

Philipp K. schrieb:
> ich habe versucht den Dateizeiger beim einlesen einer Textdatei mit
> einer Schleife an Newline auszurichten..

Wenn Du Dich am Newline "ausrichten" willst, solltest Du keine 
blockorientierte Funktion verwenden, sondern eine, die sich auch am 
Newline "ausrichtet". Nennt sich fgets(). Das Lesen in Blöcken übernimmt 
stdio sowieso schon für Dich, von daher ergibt sich überhaupt keine 
Performance-Einbuße.

Darüber hinaus kann man sich den fseek-Kram sparen.
OP #6700882
Lesenswert?

Danke für die Antworten.

Ich habe wohl zu später Stunde das einfachste übersehen und dann noch 
Fehler eingebaut.

Die Lösung scheint der Binarymodus zu sein.. beim abändern des Codes um 
den Fehler einzugrenzen  habe ich dann noch einen Fehler eingebaut. 
Normalerweise hatte ich die Variable Seekoffset neben nlpos 
runtergezählt.

Frank M. schrieb:
> Das Lesen in Blöcken übernimmt stdio sowieso schon für Dich, von daher
> ergibt sich überhaupt keine Performance-Einbuße.

Das ist ja nur ein Test die Chunks sind 150MB groß. Mich interessiert 
der Unterschied.

Dirk B. schrieb:
> Welche Warnung kommt in Zeile 7 und 20 ?

OK mache ich, normalerweise nur Pointer vs Integer comparison beim If.
Moderator Persönliche Seite #6700907
Lesenswert?

Philipp K. schrieb:
> Die Lösung scheint der Binarymodus zu sein.

Du liest eine Text-Datei, jedenfalls hast Du das oben geschrieben.

Das Problem ist unter Windows: Im Textmodus werden die CRLF-Paare (\r\n) 
zu einen LF (\n) gemapped. Von daher kann man sich schnell in der 
Position "verzählen". Komplizierter wird es, wenn Du unter Windows eine 
Unix-Datei einliest. Da ist dann gar kein CR (\r) drin.

Umgekehrt unter Unix/Linux: Hier findet kein Mapping statt - egal ob Du 
eine Windows-Datei oder Unix-Datei einliest. Und das ist dann noch 
unabhängig, ob Du die Datei im Binär- oder Textmodus öffnest. Vorteil: 
"Verzählen" kann man sich hier nicht.

> Das ist ja nur ein Test die Chunks sind 150MB groß.

Was für Chunks? Ich dachte, es geht um eine Text-Datei?

> Mich interessiert der Unterschied.

Welcher Unterschied?
OP #6700936
Lesenswert?

Frank M. schrieb:
> Du liest eine Text-Datei, jedenfalls hast Du das oben geschrieben.

Ja, ich weiß aber schon wie das Byte aussieht, also kann ich die auch in 
Bytes lesen. Die kann aber auch 1GB groß sein. Von Byte zu Char ist ja 
jetzt nicht die Welt.

Frank M. schrieb:
> Das Problem ist unter Windows: Im Textmodus werden die CRLF-Paare (\r\n)
> zu einen LF (\n) gemapped.

Das habe ich auch schon herausgefunden, dazu noch die ganzen 
Problematiken. Fseek64 etc.

Frank M. schrieb:
> Welcher Unterschied?

Ob fgets nicht vielleicht einen Overhead produziert. Mir sind die 
Newlines nicht wichtig, für diesen Fall der Optimierung der mich 
interessiert darf zwischen zwei Newlines kein Buffer enden und kein 
buffer anfangen. Das war meine Idee.
OP #6700978
Lesenswert?

Dirk B. schrieb:
> Da hast du einen Fehler. Der ist zwar nicht in der Zeile mit dem if,
> aber führt dazu dass dein Programm nicht funktioniert.

Naja, gewundert habe ich mich schon..

Mein eigentliches Programm lief schon, nur das fread mit fseek nicht 
dort wo ich dachte gestartet hat. Wie hier schon geschrieben wurde liegt 
das an der Implementierung von fread bei erstellen eines Dateizeigers im 
Textmodus "r" anstatt "rb". Wobei es noch andere Seiteneffekte gibt. Ich 
teste das auf onlinegdb.com, da muss man erst auf Debug umstellen damit 
man den Kern des SegFaults bekommt.

Den Fehler habe ich  bei reduzierung des eigentlichen Problems 
eingebaut.

Danke, ich werde das mal auf dem Rechner anschauen, bin gespannt.
OP #6701031
Lesenswert?

Klappt nicht. Dann muss ich mir etwas anderes überlegen.

ftell liefert immer ein Vielfaches von buffersize egal wie ich mit 
SEEK_SET oder SEEK_CUR die Position verschiebe.

Hat das vielleicht mit einer Optimierung vom Compiler zu tun?

EDIT: scheint doch zu laufen, habe da einen Workaround gefunden.
OP #6701063
Lesenswert?

Mathias A. schrieb:
> Das ist doch ein Array von Pointern auf char, und kein Array von chars,
> oder?

Ja, ups ich glaube das wars
1
#include <stdio.h>
2

3
int
4
main ()
5
{
6
  int intsize = 128;
7
  char buffer[intsize];
8
  buffer[intsize - 1] = '\0';
9
  FILE *fp = fopen ("list.txt", "rb");
10
  int cnt = 0;
11
  unsigned long seekoff = 0;
12
  while (1)
13
    {
14
      if (fread (buffer, intsize - 1, 1, fp))
15
  {
16
    cnt++;
17

18
    seekoff = ftell (fp);
19
    //  printf ("loop %d\n", cnt);
20
    int nlpos = intsize - 1;
21
    while (buffer[nlpos] != '\n')
22
      {
23
        nlpos--;
24
        seekoff = seekoff - 1UL;
25
      }
26
    //printf("%lu",seekoff);
27
    fseek (fp, seekoff, SEEK_SET);
28
    buffer[nlpos] = '\0';
29
    printf ("%s", buffer);
30

31
  }
32
      if (cnt > 5)
33
  break;
34
    }
35
  fclose (fp);
36
}

Da habe ich mich wohl bei der Fehlersuche verstrickt.. das war vorher 
eine Initialisierung mit  malloc.
OP #6701264
Lesenswert?

Dirk B. schrieb:
> Aber hey, das ist ja „nur“ eine Warnung. Die muss man nicht beachten.

Ich hatte diese Warnung nicht.. Außerdem hab ich da zuviel 
verschlimmbessert um das Beispiel klein zu halten.

Mathias A. schrieb:
> Ursache zu finden ist... :-o

Jo.

Sebastian schrieb:
> Was passiert denn am Dateiende wenn nur noch weniger als 127 Bytes zu
> lesen sind?

Es ist ja nur ein Problembeispiel. Man muss die Dateigröße auf die 
durchlaufenen Blöcke gegenrechnen und einen definierten Abschlussblock 
der Restgröße hinter der Schleife lesen.

Meine Idee war da, die Blockgröße zur Dateigröße anzupassen und unter 
der Buffergröße nur einmal einzulesen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren