Mètodes

42 (II): get_next_line, llegir fitxers línia a línia

Buffers estàtics i memòria entre crides: el projecte que ensenya què passa realment quan llegim un fitxer.

42 (II): get_next_line, llegir fitxers línia a línia

De petits, tots hem llegit fitxers línia a línia en algun llenguatge: readline, fgets, el que sigui. A 42 això no existeix: tens read, un descriptor de fitxer i la teva capacitat d’organitzar la memòria. El projecte es diu get_next_line: una funció que, cridada en bucle, retorna una línia de cada vegada d’un fitxer qualsevol.

El problema

La dificultat no és llegir: és retornar exactament fins al salt de línia quan read treballa amb blocs. La funció llegeix del fitxer en trossos d’una mida fixa (BUFFER_SIZE, que en les proves poden canviar), i una línia pot ser més curta que el bloc, molt més llarga, o acabar sense salt al final del fitxer. A més, entre crida i crida has de recordar per on t’has quedat, i en la part bonus, fer-ho amb diversos fitxers oberts alhora sense barrejar-los. I tot sense cap fuita de memòria, perquè cada byte compta.

Com el vaig abordar

La peça central és un buffer estàtic: una zona de memòria que sobreviu entre crides i guarda el que has llegit i encara no has consumit. Cada crida, la funció mira si al buffer ja hi ha una línia completa; si no n’hi ha, torna a llegir del fitxer i ho afegeix; quan apareix el salt de línia, retalla la línia, la retorna i deixa la resta al buffer per a la propera. Sona senzill, però el detall amagat és la varietat de casos: fitxers buits, diverses línies buides seguides, l’última línia sense salt… Em vaig fer els meus propis fitxers de prova —un amb línies curtes, un amb una línia kilomètrica, un de buit— i vaig provar amb BUFFER_SIZE d’1 fins a valors enormes per comprovar que el comportament era sempre el mateix. També vaig guardar una versió comentada del codi per estudiar-la amb calma: al repositori, 42_get_next_line, hi conviuen la versió obligatòria, la bonus i diversos mains de prova.

Què en vaig treure

Aquest projecte em va canviar la relació amb read: abans era «la crida que llegeix fitxers»; ara sé que llegeix bytes en blocs, que pot retornar-ne menys dels que demanes i que la shell, els scripts i tota la resta viuen damunt d’aquesta mecànica. També em va deixar clar el valor d’una variable estàtica ben entesa i, sobretot, l’hàbit de provar els casos que no surten al subjecte. Hi ha una satisfacció concreta en veure el mateix codi llegir bé un fitxer amb línies d’un caràcter i una altra d’un milió.