C Programmering Filhantering med öppen (), läs (), skriv () och stäng () De tidigare exemplen på filhantering handlar om File Control Blocks (FCB). Under MSDOS v3.x (eller högre) och UNIX-system görs filhantering ofta med hjälp av handtag, snarare än filkontrollblock. Skriva program som använder handtag säkerställer portabilitet av källkod mellan olika operativsystem. Med hjälp av handtag kan programmeraren behandla filen som en ström av tecken. De tillgängliga åtkomstlägena är De behörigheter är funktionen Öppna () ger ett heltal, som används för att referera till filen. Om det inte lyckas returnerar det -1, och ställer in den globala variabeln errno för att ange feltypen. Read () - funktionen försöker läsa nbytes från filen som är associerad med handtaget, och placerar tecknen i buffert. Om filen öppnas med hjälp av OTEXT, tar den bort vagnens avkastning och upptäcker slutet på filen. Funktionen returnerar antalet byte som läses. I slutet av filen returneras 0, om felet returnerar -1, ställer du in Errno för att ange vilken typ av fel som inträffade. Funktionen write () försöker skriva nbytes från bufferten till filen som är associerad med handtaget. På textfiler expanderar varje LF till en CRLF. Funktionen returnerar antalet byte som är skrivna till filen. Ett returvärde på -1 visar ett fel, med errno inställd på lämpligt sätt. Funktionen nära () stänger filen som är associerad med handtaget. Funktionen returnerar 0 om det lyckas, -1 för att indikera ett fel, med errno inställd på lämpligt sätt. Upphovsrätt B Brown. 1984-1999. Alla rättigheter reserverade. Binära filer med C R. A. Ford Department of Math. och datalogi Mount Allison University Sackville, NB Introduktion Att använda strömmar för filbehandling är säkert möjligt i C, men de flesta C-läroböcker innehåller inte någon information om den fullständiga funktionaliteten i strömmar. Detta dokument har utformats för att hjälpa studenter med bakgrund i C och datastrukturer med en fullständig beskrivning av C-strömbiblioteket. Dokumentet är baserat på GNU CPP-bibliotekets dokumentation som ibland inte är lätt att läsa, speciellt utan exempel. Införings - och extraktionsoperatörerna (dvs ltlt och är avsedda att användas av program för skrivning till och läsning från textfiler antas att programmeraren är bekant med skillnaderna mellan dessa två filformat. I verkligheten finns det dussintals tillägg med lite dokumentation av vanliga textflöden. En extra sektion läggs till i det här dokumentet vid en senare tidpunkt. Grunderna i File IO Åtkomst till en binär fil från ett C-program (genom att inte använda de gamla C-funktionerna) kräver först att en strömvariabel läggs till filen . De vanliga strömklasserna av strömmen (utdatafilström) och ifstream (inmatningsfilflöde) är fortfarande de typer av strömmar som ska användas. En ytterligare typ som kallas en fstream är tillhandahållen som möjliggör filer som kan skrivas till och läsas från om detta är en önskvärd egenskap (det är ofta fallet med design av databas typprogram). Innan någon operation kan ske på en fil måste det naturligtvis öppnas. När du är färdig med filen, Det bör stängas för att undvika förlust av data. Öppna en ström Omströmmen och uppströms har alla medlemsfunktioner som heter open som används för att fästa strömmen till ett fysiskt filnamn och öppna filen för antingen läsning eller skrivning. Funktionen öppen medlem ger också ett par valfria argument som inte ofta beskrivs. Den vanligaste prototypen för den här funktionen är det format som Ive använde indikerar att mod och prot argument är valfria. Det första argumentet är alltid namnet på filen på skivan som strömmen ska bifogas till. Const modifier ingår så att en programmerare kan skriva namnet på filen (inuti dubbla citat) i funktionssamtalet. Den enda knepiga delen om att använda den öppna medlemsfunktionen är under DOS-baserade system (inklusive Windows), där kataloger är åtskilda med en återkallelse att backslash-tecknet har en särskild betydelse i C-strängar. Prot-parametern används för att ange skydd (tillstånd) för filen under flera operativsystem som Unix. Det låter dig ange vilka användare som får se den här filen. Under DOSWindows används denna parameter aldrig. Modusparametern lämnas vanligen vid hantering av textfiler, men det finns några väldigt användbara situationer under binära filer för vilka denna parameter måste ställas in. Det finns ett antal alternativ som kan ges för denna parameter. Om du behöver ange mer än en av dem placerar du bara en vertikal streck mellan dem. ios :: in Detta indikerar att strömmen kommer att användas för inmatning. Det kan tyckas överflödigt för omströmmar som automatiskt markeras för inmatning när de öppnas, men det måste användas ibland. När du ringer upp utan någon andra parameter antas parametern vara ios :: men om du ger någon annan parameter som ios :: binär måste du ange att filen är en inmatningsfil också. ios :: out Detta indikerar att strömmen kommer att användas för utmatning. Liksom ios :: i detta kan tyckas överflödig för strömmen s, men av samma anledning som ovan måste det vanligtvis ges. Ios :: ate Detta gör att filpekaren pekar i slutet av filen när filen öppnas. ios :: trunc Detta gör att alla befintliga data i filen ska kasseras (raderas) när filen öppnas. Var försiktig så att du inte använder det här alternativet på en fil som du inte vill ha förstört ios :: binär Detta gör att filen kan nås som en binär fil. Troligtvis måste du ange det här alternativet. Om du glömmer att ställa in det här alternativet kommer många konstiga problem att uppstå när du läser vissa tecken som slutet på rad och slutet på filen. Exempel på att öppna en binär fil: Skriva till en binär fil Jag nämnde en gång att ltlt används för att skriva data till en textfil. Om du hade en variabel x som innehöll värdet 354 och du använde utdelningen statlt ltlt x så skulle karaktären 3, tecknet 5 och tecknet 4 skrivas (i ASCII-form) till filen. Detta är inte binär form som bara skulle kräva 16 bitar. Klassen avströms tillhandahåller en medlemsfunktion med namnet skriv som tillåter information att skrivas i binär form till strömmen. Prototypen för skrivfunktionen är Den här funktionen gör att n byte skrivs från minnesplatsen som ges av bufferten till disken och flyttar filpekaren framför n byte. Parametertyperna kräver lite förklaring. Även om returtypen är ofstreamamp ignoreras vanligtvis avkastningsvärdet av de flesta programansvariga. Buffertpekaren är av typen void vilket gör det möjligt för vilken typ av variabel som helst som första parameter. Du borde inte skriva funktioner med tomrumparametrar, det här är en väldigt knepig del av programmeringen. Typen strömmar är helt enkelt ett positivt heltal. Det är sällsynt att du kommer att veta exakt hur många byte en viss variabel är. För att få denna information, ger C ett makro (det är en funktion) som heter sizeof som tar exakt en parameter och returnerar parameterns storlek i termer av byte som krävs för lagring. Nedan visas ett exempel på hur storleksanvändaren använder för att få storleken på en variabel och skriva innehållet i en variabel till disken. Observera användningen av en struktur i stället för en klass som du inte ska använda den här metoden för att skriva klasser till binära filer. Se avsnittet "Skriva klasser till filer" för en beskrivning av hur detta ska ske. Läsa från en binär fil Att läsa data från en binär fil är precis som att skriva det förutom att funktionen nu kallas läs istället för att skriva. När du läser data från en fil finns det några nya saker att se upp för: Det är ansvaret för programmeraren för att säkerställa att bufferten är tillräckligt stor för att hålla alla data som läses. Följande kodsegment skulle antagligen resultera i en krasch om inte storleken på ett heltal var 7 byte (osannolikt tal): int main () int x ifstream infile infile. open (silly. dat, ios :: binär ios :: in) infile. read (ampx, 7) läser 7 byte i en cell som är antingen 2 eller 4 Efter att ha läst något från filen, måste funktionen fail () anropas för att avgöra om operationen slutfördes framgångsrikt. I C orsakar inga filoperationer programmet att sluta. Om ett fel inträffar och du inte kontrollerar det, körs ditt program otillförlitligt. Se vidare ett avsnitt i det här dokumentet om detektering av fel. Filpekare När data läses från eller skrivs till en fil, sätts data eller tas från en plats i filen som beskrivs av filpekaren. I en sekventiell åtkomstfil läses information alltid från början till slut och varje gång n byte läses eller skrivs flyttas filpekaren n byte framåt. I en slumpmässig åtkomstfil tillåts vi att flytta filpekaren till olika platser för att läsa data på olika platser i en fil. Tänk på en databas full av affärsposter. När objektet är skannat vid kassan används streckkoden för att leta upp en beskrivning och pris på objektet. Om filen var sekventiell åtkomst, skulle vi börja söka i början av filen, vilket är troligen långsammare än vi skulle vilja. Det här är inte en kurs i filbehandling, men det räcker att säga att om vi skulle kunna flytta filpekaren direkt till posten som innehåller data, skulle vi behöva läsa från filen bara en gång. Tellp () medlemsfunktionen har en prototyp av formuläret Den här funktionen accepterar inga parametrar, men returnerar den plats som anges i byte från början av filen där filpekaren sitter för tillfället. Nästa läsning eller skrivning kommer att äga rum från denna plats. Searchp () medlemsfunktionen har en prototyp av blankstegets blanka sökpost (streampos location, int relative) Detta gör att filpekaren flyttar till en annan plats i filen. Platsen anger antalet bitgrupper som ska användas för att bestämma platsen och den relativa parametern anger om det här är någon form av absolut eller relativ positionsförfrågan. Möjliga värden för relativa är: ios :: beg Detta indikerar att platsen är antalet byte från början av filen. ios :: cur Detta indikerar att platsen är antalet byte från den aktuella filpekaren. Detta möjliggör en relativ positionering av filpekaren. ios :: end Detta indikerar att platsen är antalet byte från slutet av filen. Vi betraktar ett exempel som använder både att skaffa och ställa in filpekaren plats: int main () int x streampos post ifstream infile infile. open (silly. dat, ios :: binära ios :: in) infile. seekp (243, ios: : beg) flytta 243 byte till filen infile. read (ampx, sizeof (x)) post infile. tellg () cout ltlt Filpekaren är nu på plats ltlt pos ltlt endl infile. seekp (0, ios :: end) söka till slutet av filen infile. seekp (-10, ios :: cur) säkerhetskopiera 10 byte infile. close () Skriva klasser till binära filer Det enklaste sättet att lagra poster i filer är att använda en struktur Om du håller spårning av poster i minnesstrukturer med klasser, då sparas dessa klasser till disken lite extra arbete. Du kan inte bara använda en skrivmedlemsfunktion och ge adressen till objektet som bufferten. Anledningen till detta är förekomsten av medlemsfunktioner. Det skulle inte vara meningsfullt att spara medlemsfunktionerna som dessa medlemsfunktioner äntligen blir sparade som minnesplatser, vilket skulle få datorn att krascha om du någonsin laddat en från en skiva med en gammal minnesplats. Det är möjligt att skriva objekt till disk men det kräver att objektet har en medlemsfunktion som är associerad med den. Mitt vanliga sätt är att infoga en medlemsfunktion som heter läs och skriv i varje medlemsfunktion. Dessa funktioner bör ta en fstream som en parameter som strömmen för att rädda sig till. Ditt program ska sedan öppna strömmen och ringa medlemsfunktionen med lämplig ström. Medlemsfunktionen ska sedan gå igenom varje datafält för objektet som skriver ut dem i en viss ordning. Funktionen avläst medlem måste hämta informationen från skivan i exakt samma ordning. Exemplet för det här avsnittet är lite inblandat, så jag eliminerade funktionen för icke-filmedlemmar. Börja inkludera ltiostream. h include ltstdlib. h include ltfstream. h Vad gick fel I det här avsnittet kommer jag att påpeka ett par metoder för att bestämma om en filoperation var framgångsrik och om inte ett antal metoder för att bestämma ungefär vad som gick fel . Efter varje diskoperation kommer ett välskriven program att ringa medlemsfunktionen misslyckas () för att se om operationen är klar. Det är upp till programmeraren att bestämma vad som ska hända när en filoperation går illa. I huvudsak finns det tre möjligheter: Ignorera problemet och hoppas det aldrig händer. Detta är ett bra tillvägagångssätt för att hantera fel för små program skrivna för att testa en idé, men en helt fungerande version av ett program borde aldrig utgå ifrån att användaren inte gör ett misstag. Om ett fel inträffar, ring avstängning (EXITFAILURE) och avsluta programmet. Det här är lite bättre än att bara hoppas att det inte händer, men i en fullständig version av ett program kan detta vara en verklig olägenhet för användaren. Tänk på vad som skulle hända om du spenderade 5 timmar att skriva en uppsats och försökte spara den till T: som inte existerade. Om ditt program bara avbröts så skulle du ha tappat 5 timmars arbete. När ett fel uppstår, låt användaren försöka rätta till felet och försök igen. Detta är den föredragna metoden vad gäller användaren, men är vanligtvis inte trivial att programmera. Du bör försöka genomföra detta så mycket som möjligt. En olycklig situation uppstår vid hantering av fel, de är i allmänhet fysiska saker som gör att de är beroende av operativsystemet. Därefter kommer jag att lista ANSI-standarden (approach) för att hantera fel och DOS-metoden för att hantera fel. ANSI-tillvägagångssättet är mycket mer allmänt och därför kommer felmeddelandena inte att vara exakta, men ANSI-metoden kommer att fungera oavsett vilken C-kompilator du använder. DOS-felhanteringen eliminerar viss förvirring om vad som hände men det är uppenbart bara bra på DOS-maskiner som stöder biblioteket (Turbo C, Borland C och GNU G stöder detta bibliotek). För att göra saker lite blekare verkar det inte finnas något felstöd som är inbyggt i andra strömmar än funktionen fail (). För att bekämpa fel måste vi lita på några befintliga C-funktioner som inte är något problem att använda från C eftersom C bara är en förlängning av C. ANSI Fel ANSI C stöder en global variabel (oh nej, en global variabel) som heter Errno som kan vara nås genom att inkludera errno. h När fel uppstår är variabeln inställd på en standard felkod som ska motsvara alla operativsystem. Det finns för många felkoder att stör lista i det här dokumentet. Vanligtvis är det bästa sättet att upptäcka alla felkoder att titta på den manuella sidan eller onlinehjälpsökning på nyckelordet errno. Inkludera filen definierar en uppsättning konstanter som kan användas för att bestämma vilken typ av fel som inträffade. Felkod 22 indikerar till exempel att filen du bara försökte öppna inte existerade. Ett något bättre sätt att säga 22 är att använda konstant ENOENT. Det finns en funktion i stdio. h heter perror som tar en sträng som en parameter. När den här funktionen kallas visas strängen på skärmen följt av ett kolon och sedan av ett meddelande som beskriver värdet i errno. Detta kan vara användbart om du inte vill skriva felhanterare och bara vill att programmet ska stanna. Nedan är ett enkelt program som läser ett filnamn från användaren, öppnar filen och visar att disken inte var klar, filen fanns inte eller standardfelmeddelandet. main () ifstream data char filnamn50 cout ltlt fil för att öppna cin. getline (filnamn, 50) data. open (filnamn) om (data. fail ()) switch (errno) fall EACCES: Detta är inställt om enheten inte är klar i DOS cout ltlt Drive inte redo eller tillstånd avvisat LITE ENDL break case ANVÄND: cout ltlt Kunde inte hitta den här filen Lite Endl Break Standard: Perror (öppna data fil) exit (EXITFAILURE) Ett riktigt program skulle sedan slingas tillbaka och be användaren att försök igen. . DOS Extended Error Om du tittar på de fel som anges i ANSI-listan märker du att inte många av dem är riktigt inriktade på DOS, det vill säga du vet inte säkert om en sektor var dålig på en disk eller om drivdörren var öppen. Detta beror på att ANSI-standarden mer eller mindre definierades på UNIX-systemet, där dessa typer av fel aldrig ses av användarna. De flesta DOS-baserade kompilatorer ger ett par funktioner för att utnyttja DOS-utökat fel vilket vanligtvis ger en mycket mer exakt beskrivning av felet. Datalagring av filer i C-fil. Informationen som lagras under ett visst namn på en lagringsenhet kallas en fil. Strömma. Det hänvisar till en sekvens av byte. Textfil. Det är en fil som lagrar information i ASCII-tecken. I textfiler avslutas varje textrad med ett specialtecken som kallas EOL (End of Line) tecken eller avgränsningstecken. När denna EOL-tecken läses eller skrivs, sker vissa interna översättningar. Binär fil Det är en fil som innehåller information i samma format som det hålls i minnet. I binära filer används ingen avgränsare för en rad och inga översättningar uppstår här. Klasser för filströmsoperation avströmmen. Stream klass för att skriva på filer omströmmen. Stream klass att läsa från filer fstream: Stream klass för att både läsa och skriva fromto filer. Öppna en fil OPENING FIL ANVÄNDAR KONSTRUKTOR avstream outFile (quotsample. txtquot) utmatning endast ifstream inFile (ldquosample. txtrdquo) inmatas endast OPENING FILE ANVÄNDA öppen () Stream-object. open (ldquofilenamerdquo, läge) fromstream outFile outFile. open (quotsample. txtquot ) ifstream inFile inFile. open (quotsample. txtquot) Fillägesparameter
No comments:
Post a Comment