Forum: Editera post i binärfil (C++)

Forum huvudsida -> Programmering -> Editera post i binärfil (C++)

Sidor: 1

Till botten

Omega 20:33 - 5:e Mars 2007 | Post #1
Medlem
Inlägg: 42


Skicka PM
Hej!


Jag försöker uppdatera en enskild post i en binärfil, men lyckas endast med att skriva sönder filen, så att endast posten jag uppdaterade finns kvar.

,,r det någon flagga vid öppning av filen jag saknar eller något annat?
Jag använder g++, operativsystem Ubuntu.

-ppnar filen för läsning, söker reda på posten och sparar positionen.
  1. //Hitta en post, och returnera dess position, -1 om match inte kunde hittas.
  2. int Register::findPost(char* employeeName)const
  3. {
  4. Employee tempEmployee;
  5. int position;
  6. bool postFound = false;
  7. ifstream inFile;
  8. inFile.open( regName, ios::in|ios::binary );
  9. position = inFile.tellg();
  10. while ( inFile.read((char*)&tempEmployee, sizeof(Employee))) //Går igenom positioner.
  11. {
  12. if (strcmp( tempEmployee.namn, employeeName)==0 ) //Om vi har en namnmatch.
  13. {
  14. postFound = true;
  15. break;
  16. }
  17. position = inFile.tellg();
  18. }
  19. if(postFound == false)
  20. return -1;
  21. else
  22. return position;
  23. }


-ppnar filen för skrivning, går till sparad position, skriver, och stänger filen.
  1. bool Register::editPost(char * employeeName)
  2. {
  3. Employee tempEmployee;
  4. int position;
  5. position = findPost( employeeName );
  6. if(position > -1)
  7. {
  8. cout << "A match have been found." << endl;
  9. cout << "Please enter:" << endl;
  10. cout << "Name: ";
  11. //cin.getline( tempEmployee.namn, 19);
  12. cin >> tempEmployee.namn;
  13. cout << "Room number: ";
  14. cin >> tempEmployee.rumsNummer;
  15. cout << "Telephone number: ";
  16. cin >> tempEmployee.telefonNummer;
  17. ofstream utFil(regName, ios::out|ios::binary);
  18. utFil.seekp(position);
  19. utFil.write((char*)&tempEmployee, sizeof(Employee));
  20. utFil.close();
  21. return true;
  22. }
  23. else
  24. {
  25. cout << "No match could be found" << endl;
  26. cout << "for " << employeeName << endl;
  27. return false;
  28. }


-------------------------
Fall omkull sju gånger och res dig upp åtta.

Senast redigerad 20:44 - 5:e Mars 2007


Independence 20:54 - 5:e Mars 2007 | Post #2
Administratör
Inlägg: 1800


Skicka PM
Hur fungerar det här egentligen (char*)&tempEmployee ?
Inte för jag kan nåt om sånt här, men det känns som man borde ha någon serialize() eller nåt?

-------------------------

Vi är riddarna som säger fiskbulle!





Omega 21:00 - 5:e Mars 2007 | Post #3
Medlem
Inlägg: 42


Skicka PM
Employee är en enkel klass som ser ut så här.

  1.  
  2. class Employee
  3. {
  4. public:
  5. char namn[30];
  6. int rumsNummer;
  7. char telefonNummer[15];
  8. };


Och funktionerna read och write tar endast emot en pekare av typen char *, varför en cast görs på den pekare som & ger.


-------------------------
Fall omkull sju gånger och res dig upp åtta.



ozamosi 21:44 - 5:e Mars 2007 | Post #4
Administratör
Inlägg: 1129


Skicka PM
Jag har för mig att alla filer som öppnas bara för skrivning töms helt och hållet i öppningsögonblicket. Jag minns inte hur man löser det.

-------------------------
Ljusblå



Slash 10:32 - 6:e Mars 2007 | Post #5
Medlem
Inlägg: 141


Skicka PM
Det är väl oftast inte att rekommendera att skriva ut en hel strukt i ett svep, p.g.a. padding. Det kan innebära att om du kompilerar ditt program med en annan kompilator så går de gamla datafilerna ej att läsa.

Det bästa är, som sagt, någon typ a serializering. ,,r inte så avancerat som det låter, det är bara att skriva ut varje variabel för sig, så att du senare kan återskapa objektet.

Till exempel:
  1. #include <istream>
  2. #include <ostream>
  3. class MyClass
  4. {
  5. public:
  6. void write(std::ostream &stream)
  7. {
  8. // Skriv varje variabel för sig till strömmen, t.ex:
  9. stream.write(myVar, len);
  10. // etc..
  11. }
  12. void read(std::istream & stream)
  13. {
  14. // läs varje variabel för sig från strömmen i samma ordning som du skrev den
  15. stream.read(myVar, etc.. etc..
  16. }
  17. private;
  18. char myVar[10];
  19. };


Sen använder du bara dig av
  1. #include <fstream>
  2. Employee tempEmployee;
  3. // fyll i fälten för den anställde
  4. ...
  5. // skriv ut till fil:
  6. ofstream utFil(regName, ios::out|ios::binary);
  7. tempEmployee.write(utFil);
  8. // Sen kan du för att debugga t.ex enkelt skriva ut till skärmen med:
  9. tempEmployee.write(std::cout);


Vidare så är det i allmänhet lättast, snabbast och snyggast att läsa in all data i minnet, modifiera datat där och sedan skriva ut allt till din fil i slutet. Detta är endast dåligt om du skulle ha enormt stora datamängder.

EDIT. Stavfel

-------------------------
Ingen sigantur!

Senast redigerad 15:52 - 6:e Mars 2007


Omega 18:48 - 6:e Mars 2007 | Post #6
Medlem
Inlägg: 42


Skicka PM
Hej!

Ozamozi, jag har inte hunnit testa ditt tips ännu. Skall testa att använda fstream och både ios::in och ios::out vid öppingen för att se om det blir någon skillnad.


Slash, tipset om paddingen och serialisering skall jag lägga på minnet, hade faktiskt inte tänkt på det.
Men jag tror inte att det är det som är problemet nu, då jag håller mig till en kompilator.

Jag har inga problem att läsa skriva till filen, och sedan kunna läsa tillbaka det skrivna, förutsatt att jag skriver filen från början till slut.

Problemet är att jag vill kunna gå in i filen och skriva om en specifik post utan att skriva om hela filen.
Jag hade tänkt att använda read, tellg, seekp och write i den ordningen för att uppdatera posten, men filen jag skriver till innehåller sedan alltså bara den senaste posten.



-------------------------
Fall omkull sju gånger och res dig upp åtta.



Slash 20:09 - 6:e Mars 2007 | Post #7
Medlem
Inlägg: 141


Skicka PM
    Citat av ozamosi:
Jag har för mig att alla filer som öppnas bara för skrivning töms helt och hållet i öppningsögonblicket. Jag minns inte hur man löser det.


ios::app ska inte trunkera innehållet vad jag minns. Detsamma verkar även gälla för ios::ate. -ppna den får både skrivning och läsning bör ju också fungera ja.

-------------------------
Ingen sigantur!

Senast redigerad 20:10 - 6:e Mars 2007


Sidor: 1

Forum huvudsida -> Programmering -> Editera post i binärfil (C++)
Atom feed

Du får inte posta i den här tråden | Till toppen