Fájl kezelés C-ben

Fórumok

Segítséget szeretnék kérni, hogyan lehet C-ben egy iso8859-2 kódolású txt fájl sorait beolvasni, ha nem tudom előre egy sor hosszát? Nem akarok egy nagy buffert lefoglalni, van -e arra mód, hogy megtudjam a beolvasandó sor hosszát, hogy dinamikusan tudjam a buffer méretet ehhez állítani? Vagy van erre valami más, szebb módszer?

Hozzászólások

Foglalsz neki valamekkora helyet malloc()-kal, ha mar a vege fele jarsz, akkor foglalsz meg hozza realloc()-kal.

Lehet, hogy butaságot írok, de mintha az fgets elvárná, hogy maximalizáld a beolvasandó sor hosszát. Ergó akkor már nyugodtan lehet ekkora puffert is foglalni. Arról nem is beszélve, hogy szerintem a soronkénti alloc / realloc nem kicsit lassítja a dolgot.

keresem a legfrankóbb módszert erre. sok helyen láttam azt, hogy lefoglalnak mondjuk egy 4 vagy 8KB-s buffert és abba olvasnak, vagy egy tömbbe, de nem lehet ezt úgy, hogy annyit foglalni le amekkora a beolvasandó sor? utána felszabadítani, majd allokálni megint amekkora a következő. szóval jó ez a lefoglalok előre egy buffert, de mi van ha extrém hosszú egy sor?

Ha extrém hosszú a sor, akkor szívás van.
A legegyszerűbb (dinamikus) megoldás: van egy puffered amibe ált befér egy sor (mondjuk 1024), egyszerre ennyit olvasol a fájlból. Keresel benne sorvége jelet - amíg van, visszaadod addig és a másik pufferben lévő maradékot. Ha nincs, vagy maradt, azt hozzáadod a másik (maradvány) pufferedhez - ennek a méretét realloc-al állítod kellő méretűre.
Bonyolult, neked kell csinálni a sorvége keresést és kezelést.

Egyszerűbb az fgets, oszt ha elszáll, akkor allokálsz kétszer akkora puffert, és újra próbálkozol.

Extrém hosszú sorokat nem fogja beolvasni az fgets(). Hiszen meg kell adni neki, mennyit olvasson be maximum, ha ennél hosszabb egy sor, akkor azt két (vagy több) sornak fogja venni (ha jól emlékszem). Szerintem nem véletlenül használják ezt a módszert (x kb puffer, aztán hajrá...)
Vagy valami mással próbálsz beolvastatni?
Vagy várható, hogy extrémen hosszú sorok lesznek?

igazából én speciel az fscanf -re gondoltam ugyanis azzal lehet sort beolvasni, hiszen megadható olyan minta amire ráillik a sztring\n vagyis a "%s\n" és így pon egy sort fog beolvasni, ami nekem ideális lenne.. főleg ha tudnám, hogy ez összesen hány bájt mert akkor a beolvasás előtt le tudnám allokálni :-)
és mivel ez ilyen beadandó feladat lesz, így nyilván valóan az extrém dolgokat fogják vizsgálni, hogy mennyire tűri azok kezelését.. gondolom én.

Szeretem az ilyen épületes kérdéseket :-D

Tudtommal C-re kérdeztél, de feltételezted, hogy mint a Pascalban, tárolódik a sztring hossza. De nem. Innentől olyat nem tudsz, hogy ha tudom a hosszát, annyi memóriát foglalok le.
Tessék lefoglalni valamennyit, abba beolvasni (ha akarod fgets-sel, ha akarod fread-del, ha akarod mással). Ha olyan eszközt használsz, amelyik ellenőrzi helyetted a sorvéget jó, ha nem olyat, tedd meg. Ha volt sorvég megvagy, ha nem volt, újabb memóriafoglalás, újabb olvasás.

mmap(). Ez virtuálisan az egészet berántja a memóriába, nem is kell allokálni semmit, ráadásul ha egyszerre több processz is így tesz a fájllal, akkor géped memóriájában csak egyszer lesz benne, nem annyiszor ahány processz beolvasta.

Nem kellene egy iskolai feladatból csodákat kihozni... kb ilyesmi:

char linebuff [4096];
int len, leave;
long lineno;

for (leave= 0, lineno= 0; ! leave && fgets linebuff, sizeof (linebuff), f) != NULL;) {
++lineno;
  len = strlen (linebuff);
  if (len==0 || linebuff[len-1] != '\n') {
    fprintf (stderr, "Line %ld: too long or contains 0x00\n", lineno);
    leave = 1;
  } else {
  /* do something */
  }
}

Amúgy meg természetesen mindenkinek köszönöm a hozzászólást, nem akarnék ölre menő vitát kirobbantani, mert annyira tényleg nem bonyolult, csupán felötlött bennem a kérdés, hogy a sok megoldási lehetőség közül melyik az amit a legjobban lehetne használni erre. nekem speciel ez a getline nagyon bejön, elolvastam a manuálját, megnéztem a példát ami a man-ban van és nagyon szuperül működik is. természetesen ugyanolyan jól működik az összes többi változat is. A program ami ezt használná pedig egy iso8859-2 --> repülő ékezet ; repülő ékezet --> iso8859-2 -es konverter lenne. Az input lehet rendes ékezetes vagy repülő ékezetes egy fájlba sorokra bontva, melyből egy másik fájlba kell elkészíteni a konverziós párját, mint kimeneti fájl.

És egy ilyen progihoz miért kell sorokat olvasni? A newline mennyiben más, mint egy szóköz vagy egyéb írásjel? Simán jó lett volna, hogy olvasol mondjuk 1024 byte-ot, vagy akár csak 1-et getchar()-ral, feldolgozod, kiírod, esetleg amikor repülőből kódolsz vissza, akkor a végén maradhat 1 karakter amit még nem tudsz feldolgozni, azt viszed "tovább", olvasol hozzá még... Mondjuk ha én számtech tanár lennék, nagyon-nagyon csúnyán néznék arra, aki egy triviális véges automatát úgy kódol le, hogy tetszőlegesen nagyra nőhet a memóriaigénye.

nem kell sorokat olvasni, de lehet. Az feladatban még a sorok hosszát is maximalizálták 80 karakterben, pusztán kíváncsiságból kérdeztem meg. az előre lefoglalt bufferbe olvasás és annak feldolgozása tökéletesen jó, meg a karakterek egyesével beolvasása is, bár a buffer szerintem jobb. de láss csodát létezik egy sor olvasó függvény is, méghozzá teljesen klasszul.