C Programmeerhandleiding over het willekeurig verwerken van bestanden

Afgezien van de eenvoudigste toepassingen, moeten de meeste programma's bestanden lezen of schrijven. Het kan alleen zijn voor het lezen van een configuratiebestand, of een tekstparser of iets geavanceerder. Deze tutorial richt zich op het gebruik van bestanden met willekeurige toegang in C.

Programmering Random Access File I / O in C

binair bestand
D3Damon / Getty Images

De basisbewerkingen voor bestanden zijn:

  • fopen - open een bestand - specificeer hoe het wordt geopend (lezen / schrijven) en typ (binair / tekst)
  • fclose - sluit een geopend bestand
  • fread - lezen uit een bestand
  • fwrite - schrijf naar een bestand
  • fseek / fsetpos - verplaats een bestandsaanwijzer naar ergens in een bestand
  • ftell / fgetpos - u vertellen waar de bestandsaanwijzer zich bevindt

De twee fundamentele bestandstypen zijn tekst en binair. Van deze twee zijn binaire bestanden meestal eenvoudiger te verwerken. Om deze reden en het feit dat willekeurige toegang tot een tekstbestand niet vaak nodig is, is deze tutorial beperkt tot binaire bestanden. De eerste vier hierboven genoemde bewerkingen zijn voor zowel tekstbestanden als bestanden voor willekeurige toegang. De laatste twee alleen voor willekeurige toegang.

instagram viewer

Willekeurige toegang betekent dat u naar elk deel van een bestand kunt gaan en er gegevens uit kunt lezen of schrijven zonder dat u het hele bestand hoeft door te lezen. Jaren geleden werden gegevens opgeslagen op grote rollen computertape. De enige manier om op een punt op de band te komen was door de hele band door te lezen. Toen kwamen er schijven langs en nu kun je elk deel van een bestand direct lezen.

Programmeren met binaire bestanden

Een binair bestand is een bestand van elke lengte dat bytes bevat met waarden tussen 0 en 255. Deze bytes hebben geen andere betekenis dan in een tekstbestand waar een waarde van 13 betekent 'return', 10 betekent line-feed en 26 betekent 'end of file'. Software die tekstbestanden leest, heeft te maken met deze andere betekenissen.

Binaire bestanden zijn een stroom bytes en moderne talen werken eerder met streams dan met bestanden. Het belangrijkste onderdeel is de gegevensstroom in plaats van waar deze vandaan komt. In Ckunt u de gegevens beschouwen als bestanden of streams. Met willekeurige toegang kunt u elk deel van het bestand of de stream lezen of ernaar schrijven. Met sequentiële toegang moet je vanaf het begin als een grote tape door het bestand lopen of streamen.

Dit codevoorbeeld laat zien dat een eenvoudig binair bestand wordt geopend om te schrijven, met daarin een tekstreeks (char *). Normaal zie je dit bij een tekstbestand, maar je kunt ook tekst schrijven naar een binair bestand.

Dit voorbeeld opent een binair bestand om te schrijven en schrijft er vervolgens een char * (string) in. De variabele FILE * wordt geretourneerd door de aanroep fopen (). Als dit niet lukt (het bestand kan bestaan ​​en open of alleen-lezen zijn of er kan een fout zijn met de bestandsnaam), dan geeft het 0 terug.

Met de opdracht fopen () wordt geprobeerd het opgegeven bestand te openen. In dit geval is het test.txt in dezelfde map als de applicatie. Als het bestand een pad bevat, moeten alle backslashes worden verdubbeld. "c: \ folder \ test.txt" is onjuist; je moet "c: \\ folder \\ test.txt" gebruiken.

Aangezien de bestandsmodus "wb" is, schrijft deze code naar een binair bestand. Het bestand wordt gemaakt als het niet bestaat en als dat zo is, wordt alles wat erin zat verwijderd. Als de aanroep van fopen mislukt, bijvoorbeeld omdat het bestand open was of de naam ongeldige tekens of een ongeldig pad bevat, retourneert fopen de waarde 0.

Hoewel je gewoon kunt controleren of ft niet-nul is (succes), heeft dit voorbeeld een functie FileSuccess () om dit expliciet te doen. In Windows voert het het succes / falen van de oproep en de bestandsnaam uit. Het is een beetje lastig als u op zoek bent naar prestaties, dus u kunt dit beperken tot foutopsporing. In Windows is er weinig overhead voor het uitvoeren van tekst naar de systeemdebugger.

De fwrite () -aanroepen geven de opgegeven tekst weer. De tweede en derde parameter zijn de grootte van de karakters en de lengte van de string. Beide zijn gedefinieerd als size_t, een geheel getal zonder teken. Het resultaat van deze oproep is om telitems van de opgegeven grootte te schrijven. Merk op dat bij binaire bestanden, ook al schrijf je een string (char *), het geen enkele return of line feed karakters toevoegt. Als je die wilt, moet je ze expliciet in de string opnemen.

Bestandsmodi voor het lezen en schrijven van bestanden

Wanneer u een bestand opent, geeft u op hoe het moet worden geopend - of u het nu wilt maken of het wilt overschrijven en of het tekst of binair is, leest of schrijft en of u het wilt toevoegen. Dit wordt gedaan met behulp van een of meer bestandsmodusspecificaties die enkele letters "r", "b", "w", "a" en "+" zijn in combinatie met de andere letters.

  • r - Opent het bestand om te lezen. Dit mislukt als het bestand niet bestaat of niet kan worden gevonden.
  • w - Opent het bestand als een leeg bestand om te schrijven. Als het bestand bestaat, wordt de inhoud vernietigd.
  • a - Opent het bestand voor schrijven aan het einde van het bestand (toevoegen) zonder de EOF-markering te verwijderen voordat nieuwe gegevens naar het bestand worden geschreven; hierdoor wordt eerst het bestand gemaakt als het niet bestaat.

Het toevoegen van "+" aan de bestandsmodus creëert drie nieuwe modi:

  • r + - Opent het bestand voor zowel lezen als schrijven. (Het bestand moet bestaan.)
  • w + - Opent het bestand als een leeg bestand voor zowel lezen als schrijven. Als het bestand bestaat, wordt de inhoud vernietigd.
  • a + - Opent het bestand om te lezen en toe te voegen; de toegevoegde bewerking omvat het verwijderen van de EOF-markering voordat nieuwe gegevens naar het bestand worden geschreven en de EOF-markering wordt hersteld nadat het schrijven is voltooid. Het maakt eerst het bestand als het niet bestaat. Opent het bestand om te lezen en toe te voegen; de toegevoegde bewerking omvat het verwijderen van de EOF-markering voordat nieuwe gegevens naar het bestand worden geschreven en de EOF-markering wordt hersteld nadat het schrijven is voltooid. Het maakt eerst het bestand als het niet bestaat.

Combinaties van bestandsmodi

Deze tabel toont combinaties van bestandsmodi voor zowel tekst- als binaire bestanden. Over het algemeen leest of schrijft u naar een tekstbestand, maar niet beide tegelijk. Met een binair bestand kunt u zowel naar hetzelfde bestand lezen als ernaar schrijven. De onderstaande tabel laat zien wat u met elke combinatie kunt doen.

  • r tekst - lezen
  • rb + binair - lezen
  • r + tekst - lezen, schrijven
  • r + b binair - lezen, schrijven
  • rb + binair - lezen, schrijven
  • w tekst - schrijven, maken, afkappen
  • wb binair - schrijven, maken, afkappen
  • w + tekst - lezen, schrijven, maken, afkappen
  • w + b binair - lezen, schrijven, maken, afkappen
  • wb + binair - lezen, schrijven, maken, afkappen
  • een tekst - schrijven, creëren
  • ab binair - schrijven, creëren
  • a + tekst - lezen, schrijven, creëren
  • a + b binair - schrijven, creëren
  • ab + binary - schrijven, creëren

Tenzij je gewoon een bestand aanmaakt (gebruik "wb") of er slechts één leest (gebruik "rb"), kun je wegkomen met "w + b".

Sommige implementaties laten ook andere letters toe. Microsoftstaat bijvoorbeeld toe:

  • t - tekstmodus
  • c - vastleggen
  • n - vrijblijvend
  • S - caching optimaliseren voor sequentiële toegang
  • R - caching niet-sequentieel (willekeurige toegang)
  • T - tijdelijk
  • D - verwijderen / tijdelijk, wat het bestand doodt wanneer het wordt gesloten.

Deze zijn niet draagbaar, dus gebruik ze op eigen risico.

Voorbeeld van willekeurige toegang tot bestandsopslag

De belangrijkste reden voor het gebruik van binaire bestanden is de flexibiliteit waarmee u overal in het bestand kunt lezen of schrijven. Met tekstbestanden kunt u alleen achtereenvolgens lezen of schrijven. Met de prevalentie van goedkope of gratis databases zoals SQLite en MySQL, vermindert de noodzaak om willekeurige toegang tot binaire bestanden te gebruiken. Willekeurige toegang tot bestandsrecords is echter een beetje ouderwets, maar nog steeds nuttig.

Een voorbeeld onderzoeken

Stel dat het voorbeeld een index- en gegevensbestandpaar toont dat strings opslaat in een willekeurig toegankelijk bestand. De snaren hebben verschillende lengtes en worden geïndexeerd door positie 0, 1 enzovoort.

Er zijn twee ongeldige functies: CreateFiles () en ShowRecord (int recnum). CreateFiles gebruikt een char * buffer van grootte 1100 om een ​​tijdelijke string te bevatten die bestaat uit de format string msg gevolgd door n sterretjes waar n varieert van 5 tot 1004. Er worden twee FILE * gemaakt, beide met behulp van wb filemode in de variabelen ftindex en ftdata. Deze worden na het aanmaken gebruikt om de bestanden te manipuleren. De twee bestanden zijn

  • index.dat
  • data.dat

Het indexbestand bevat 1000 records van het type indextype; dit is het struct indextype, dat de twee leden pos (van het type fpos_t) en grootte heeft. Het eerste deel van de lus:

vult de string msg als volgt in.

enzovoorts. Dan dit:

vult de struct in met de lengte van de string en het punt in het gegevensbestand waar de string zal worden geschreven.

Op dit punt kunnen zowel de structuur van het indexbestand als de gegevensbestandstring naar hun respectievelijke bestanden worden geschreven. Hoewel dit binaire bestanden zijn, worden ze opeenvolgend geschreven. In theorie zou je records kunnen schrijven naar een positie voorbij het huidige einde van het bestand, maar het is geen goede techniek om te gebruiken en waarschijnlijk helemaal niet draagbaar.

Het laatste deel is het sluiten van beide bestanden. Dit zorgt ervoor dat het laatste deel van het bestand naar de schijf wordt geschreven. Tijdens het schrijven naar bestanden gaan veel van de schrijfbewerkingen niet rechtstreeks naar de schijf, maar worden opgeslagen in buffers van vaste grootte. Nadat het schrijven de buffer heeft gevuld, wordt de volledige inhoud van de buffer naar de schijf geschreven.

Een functie voor het spoelen van bestanden dwingt spoelen af ​​en u kunt ook strategieën voor het spoelen van bestanden opgeven, maar die zijn bedoeld voor tekstbestanden.

ShowRecord-functie

Om te testen of een bepaald record uit het gegevensbestand kan worden opgehaald, moet u twee dingen weten: waar het begint in het gegevensbestand en hoe groot het is.

Dit is wat het indexbestand doet. De ShowRecord-functie opent beide bestanden, zoekt naar het juiste punt (recnum * sizeof (indextype) en haalt een aantal bytes = sizeof (index) op.

SEEK_SET is een constante die aangeeft waar de fseek vandaan komt. Hiervoor zijn twee andere constanten gedefinieerd.

  • SEEK_CUR - zoek relatief ten opzichte van de huidige positie
  • SEEK_END - zoek absoluut vanaf het einde van het bestand
  • SEEK_SET - zoek absoluut vanaf het begin van het bestand

Je zou SEEK_CUR kunnen gebruiken om de bestandsaanwijzer vooruit te verplaatsen op grootte van (index).

Na de grootte en positie van de gegevens te hebben verkregen, blijft het gewoon om deze op te halen.

Gebruik hier fsetpos () vanwege het type index.pos dat fpos_t is. Een alternatieve manier is om ftell te gebruiken in plaats van fgetpos en fsek in plaats van fgetpos. Het paar fseek en ftell werken met int terwijl fgetpos en fsetpos fpos_t gebruiken.

Nadat het record in het geheugen is gelezen, wordt een nul-teken \ 0 toegevoegd om er een correct van te maken c-string. Vergeet het niet, anders krijg je een crash. Zoals eerder wordt fclose aangeroepen op beide bestanden. Hoewel u geen gegevens verliest als u fclose vergeet (in tegenstelling tot schrijven), heeft u een geheugenlek.

instagram story viewer