Avatar billede driis Nybegynder
06. maj 2003 - 17:41 Der er 11 kommentarer og
1 løsning

fstream filproblemer ...

Hej,

jeg har en klasse med en fstream som privat medlem. Med denne åbner jeg en fil i random access mode ( ios::in | ios::out | ios::binary ). Hvis jeg nu skriver nogle data til filen, og derefter prøver at læse dem igen, sker der nogle gange det, at det ikke er de samme data, der læses, som jeg har skrevet.

Hvad kan det skyldes ??
Avatar billede arne_v Ekspert
06. maj 2003 - 18:12 #1
Det er megt svært at sige med de oplysninger.

Vi skal nok se lidt kode.
Avatar billede driis Nybegynder
06. maj 2003 - 18:23 #2
Det vidste jeg egentlig godt - ville bare lige se om der var nogen der havde en anelse om problemet, før jeg fyldte et spørgsmål op med masser af kode.

Her er de 2 funktioner i klassen, som hhv. skriver og læser til/fra filen. Filen åbnes i klassens constructor. filIO objektet går ikke nødvendigvis ud af scope mellem 2 eller flere kald til editData eller getData - så filen lukkes altså ikke mellem læsning og skrivning:


bool filIO::editData(entry ent)
{
    if ( ent.ID > MAX_USERS - 1 || ent.ID < 0 )  // Vi kan ikke skrive på en plads > 99
        return false ;   

    if ( *(ent.name) == 0 )                // opdater places - array
        places[ent.ID] = true ;            // (Hvis første plads i ent.name = 0,
    else                                // er pladsen nu ledig)
        places[ent.ID] = false ;

    data.seekp(ent.ID * REC_LEN);        // Find den plads, der skal skrives på.

    data.write(reinterpret_cast<const char *>(&ent.ID),2) ;
    data.write(ent.name,30) ;
    data.write(reinterpret_cast<const char *>(&ent.code),2);
    data.write(reinterpret_cast<const char *>(&ent.card),2);
    data.write(&ent.status,1) ;
    data.write(STOP,1) ;
   
    return true ;
}


bool filIO::getData(const int ID,entry * ent)
{
    char tmp[2] ;
    if ( ID < 0 || ID > MAX_USERS - 1 )
        return false ;

    ent->ID = ID ;
    data.seekg(ID * REC_LEN + 2) ;    // Find det sted, navnet begynder.
    data.read(ent->name,30) ;        // Læs navn
    ent->name[30] = 0 ;                // Sørg for at navn er termineret med 0.
   
    data.read(tmp,2) ;                // Læs kode
    // De 2 læste bytes står i 'forkert rækkefølge', de konverteres til int:
    if ( tmp[0] < 0 )
        ent->code = ((tmp[1]+1) * 256) + tmp[0] ;
    else
        ent->code = tmp[1] * 256 + tmp[0] ;

    data.read(tmp,2) ;                // Læs kort
    // De 2 læste bytes står i 'forkert rækkefølge', de konverteres til int:
    if ( tmp[0] < 0 )
        ent->card = ((tmp[1]+1) * 256) + tmp[0] ;
    else
        ent->card = tmp[1] * 256 + tmp[0] ;

    data.read(&ent->status,1) ;        // Læs status
    if ( *(ent->name) == 0 )
        return false ;
    else
        return true ;
}
Avatar billede arne_v Ekspert
06. maj 2003 - 19:08 #3
1)  Har du prøvet at læse en korrekt type i.s.f. at læse 2 char og
    så konvertere ?

2)  Er du sikker på at din håndterimg af negative bytes er korrekt ?
Avatar billede arne_v Ekspert
06. maj 2003 - 19:09 #4
re 1)

short int tmp = 0;
data.read((char*)&tmp,2);

re 2)

ent->card = (tmp[1] << 8) | tmp[0];
Avatar billede driis Nybegynder
06. maj 2003 - 20:35 #5
1) Virker direkte, hvilket gør 2) overflødig - så nu er koden blevet lidt mere simpel, tak. En lidt mere intensiv test i morgen vil så vise, om problemet med at den læser forkerte data i visse tilfælde, også er væk.

Til re 2) : Er det korrekt forstået, at << operatoren her roterer bits'ne i tmp[1] 8 pladser til venstre, således at værdien kan or'es direkte med tmp[0] for at danne tallet ? Vil sådan et statement fungere - her tænker jeg på, at tmp[1] som udgangspunkt jo kun består af 8 bits - vil << operatoren så bevirke, at værdien udvides til en 16 bits værdi ?
Avatar billede arne_v Ekspert
06. maj 2003 - 20:41 #6
Du har forstået det rigtigt.

<< shifter til venstre.

Og "en char << en int konstant" giver faktisk en int altså 32 bit
(ikke en short int 16 bit).
Avatar billede arne_v Ekspert
07. maj 2003 - 13:50 #7
Virker det ?
Avatar billede arne_v Ekspert
07. maj 2003 - 13:50 #8
Og et svar i tilfælde af at det gør.
Avatar billede driis Nybegynder
07. maj 2003 - 16:50 #9
Der er stadig problemer. Jeg bruger kun de 2 ovenfor viste funktioner til at skrive / læse i filen. Alligevel sker det, at der bliver skrevet forkert til filen. Helt konkret, i linien
data.write(reinterpret_cast<const char *>(&ent.ID),2) ;

Her sker der, såvidt jeg kan se, det at der bliver skrevet 3 bytes i.s.f 2 i nogle tilfælde (ikke altid, hvilket gør problemet endnu mere mystisk). I hvert fald udmønter fejlen sig i, at første plads i ent.name bliver 0, når jeg bruger filIO::getData til at læse dataene igen.

Jeg håber, det gav mening, og at der er nogen der har en ide om hvad jeg gør galt.

arne_v >> Under alle omstændigheder falder der en flok point af til dig for hjælpen indtil videre.
Avatar billede arne_v Ekspert
07. maj 2003 - 16:55 #10
Hvad sker der hvis du bruger:

data.write((char *)(&ent.ID),2);

?
Avatar billede driis Nybegynder
07. maj 2003 - 17:17 #11
data.write((char *)(&ent.ID),2);

Giver samme problem. Jeg har nu identificeret problemet så langt, at hvis en datapost gemmes med ID = 10, så opstår problemet => Første plads i navn bliver 0 når post 10 læses igen. Problemet har også været der med andre ID numre, men i øjeblikket opstår fejlen konsekvent på ID 10. Problemet er aldrig opstået ved ID numre mindre end 10.
Avatar billede driis Nybegynder
13. maj 2003 - 18:24 #12
Problemet er der stadig. Jeg lukker spørgsmålet, men hvis der er nogen der har en idé til afhjælpning af problemet, så skriv endelig ;-) Der er 200 point til den der finder en løsning ;-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester