tutorials.de Buch-Aktion 05/2012
Seite 1 von 2 12 LetzteLetzte
ERLEDIGT
JA
ANTWORTEN
15
ZUGRIFFE
434
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    Hallo Welt

    Ich habe folgendes Problem:
    Ich möchte eine Datei binär auslesen und dann in eine andere Datei schreiben. Dazu benutze ich fread(), da fgets() ja nicht binär funktioniert. Es funktioniert soweit auch alles, nur mit meinem Versuchscode:
    Code c:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    //i = Grösse der zu kopierenden Datei, j ist der Zähler
    //char temp hat grösse [4]
    //f = zu kopierende Datei
    while(j != i)
    {
        fseek(f,j,SEEK_SET);
        fread(temp,1,1,f);
        fprintf(target,"%c",temp[0]);
        j++;
    }
    dauert das halt bei grossen Dateien ewig. Deshalb wollte ich das ganze ein wenig beschleunigen:
    Code c:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    //temp auf 1024 gesetzt
    while(j != i && (i-j) >= 10)
    {
        fseek(f,j,SEEK_SET);
        fread(temp,10,10,f);
        fprintf(target,temp);
        j = j+10;
    }
    while(j != i)
    {
        fseek(f,j,SEEK_SET);
        fread(temp,1,1,f);
        fprintf(target,"%c",temp[0]);
        j++;
    }
    Resultat: Programmabsturz. Was mache ich falsch?


    Gruss
    cwriter
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  2. #2
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Hi

    in welcher Zeile passiert es?
    Warum immer ein fseek?
    Warum 1024, wenn du nur 10 nimmst?

    printf ist auch nicht für binäres Zeug geeignet.
    Das wird der Absturzgrund sein.
    Dafür gibts fwrite.

    int i = Grösse der zu kopierenden Datei, int j ist der Zähler
    char temp hat grösse [1024]
    f = zu kopierende Datei
    target = Zieldatei
    Code cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    //öffnen...
    int k;
    while(j < i)
    {
        K = i - j;
        if(k > 1024)
            k -= 1024;
        if(k != fread(temp, 1, k, f))
            //Fehler, Ende
        if(k != fwrite(temp, 1, k, target))
            //Fehler, Ende
        j += k;
    }
    //schließen...
    Ungetestet.

    Gruß
    cwriter bedankt sich. 
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  3. #3
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    Vielen Dank für die Hilfe sheel

    Ich Trottel habe aber dem falschen char array 1024 zugewiesen Man kann ja auch schlecht 10 chars in einen 4 array schreiben...
    Jetzt funktioniert's auch.
    Zum fprintf(): Das funktioniert eigentlich gut. Ich habe mal den Test mit einer .png-Datei gemacht. Mit fgetc() / fgets() und fputc() / fputs() geht's nicht, mit fread() / fprintf() aber sehr gut.

    Naja, nochmal Danke für die Hilfe und Entschuldigung für die Nichtigkeit

    cwriter
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  4. #4
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    DOch doch, mit fgetc/fputc gehts schon auch.
    Die machen nur alles einzeln.

    Und wenns mit fprintf bei dir geht ist das nur Glück.
    Da eigentlich ein \0-terminierter String reingehört, darf das so gar nicht funktionieren.
    Hast zufällig einen \0 dahinter rein kompiliert...muss aber nicht jedesmal so sein.
     
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  5. #5
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    Ok, geht nun doch nicht. Dafür gibt's eine andere Fehlermeldung. Juchu
    Code :
    1
    2
    
    fread:
    Expression: num <= (SIZE_MAX / elementSize)
    Weisst du etwas? Code:
    Code c:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    
    int packe(char Obj1[],char Obj2[],char Ziel[])
    {
        //PACKEN
        char path[256];
        sprintf(path,"%s.xyz",Ziel);
        FILE* target = fopen(path,"wb");
        FILE* f = fopen(Obj1,"rb");
        if(f == NULL) return -1;
        unsigned long i = 0;
        unsigned long j = 0;
        char temp[102400];
        while(fgetc(f) != EOF) i++;
        printf("Dateigroesse: %d\n",i);
        fprintf(target,"%d:",i);
        
        while(j != i && (i-j) >= 100000)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,100000,100000,f);
            fprintf(target,temp);
            j = j+100000;
        }
        while(j != i && (i-j) >= 10000)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,10000,10000,f);
            fprintf(target,temp);
            j = j+10000;
        }
        while(j != i && (i-j) >= 1000)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,1000,1000,f);
            fprintf(target,temp);
            j = j+1000;
        }
        while(j != i && (i-j) >= 100)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,100,100,f);
            fprintf(target,temp);
            j = j+100;
        }
        while(j != i && (i-j) >= 10)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,10,10,f);
            fprintf(target,temp);
            j = j+10;
        }
        while(j != i)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,1,1,f);
            fprintf(target,"%c",temp[0]);
            j++;
        }
        fclose(f);

    Und, nein, ich terminiere nicht. Seltsam.

    Gruss
    cwriter
    Geändert von cwriter (15.10.11 um 13:14 Uhr)
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  6. #6
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    Nochmal Kurz: (f/s/w/v/bla-) printf DARF NICHT funktionieren.
    Das solls gar nicht. Je nach Compiler/Datei wirds manchmal funktionieren, manchmal abstürzen, manchmal falsche Daten in die Datei schreiben (Bytes auslassen oder falsche Bytes dazunehmen).

    Und zu fread/fwirte gibts mehr als einen Dokueintrag.
    Du hast 102400 Arrayelemente mit je 1 Byte,
    willst aber 100000 mit je 100000 Byte aus der Datei lesen.
    10000000000 ist zu viel für 102400.
    10GB vs 100KB
    cwriter bedankt sich. 
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  7. #7
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    Oh, na aua. Ich dachte, es seien ENTWEDER 100000 Bytes ODER 100000 Zeichen. Ich habe es jetzt auf 100 Bytes / 100000 Zeichen runtergeschraubt und es funktioniert. Auch mit fprintf(). Aber vielleicht liegt das auch am VC++ Compiler.

    Naja, nochmals Danke für die Hilfe

    cwriter
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  8. #8
    Avatar von sheel
    sheel sheel ist offline Moderator
    tutorials.de Moderator
    Registriert seit
    Jul 2007
    Beiträge
    4.501
    seufz...du wirst es schon noch merken...
    Auch MS kann nicht zaubern.

    Und Bytes/Zeichen: Es hat schon einen Sinn, dass man da ordentliche Werte eingeben sollte.
    Es wird nicht einfach multipliziert, Big/Little-Endian spielen auch eine Rolle.
    100-100 ist nicht 10000-1.

    Aber mach ruhig...
    cwriter bedankt sich. 
    Netiquette (vA §15) und Nutzungsregeln (vA §4.8) einhalten! Programmcode in Codetags/Codeboxen.
    Sehr gute Beiträge bitte Bewerten (Stern darunter oder "Danke").
    "Funktioniert nicht" ist zu ungenau! Code, Fehlermeldungen, Verhalten des Programms, ...?

  9. #9
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    So, jetzt verzweifle ich aber langsam:
    Solange ich alles in 1-Byte-Schritten mache, geht alles gut. In grösseren aber ist die entpackte Datei beschädigt... Ich probier's jetzt mal mit fwrite(). Hoffe mal, dass das geht.

    cwriter

    EDIT: Ja fail, jetzt weiss ich auch, weshalb das ohne \0-Terminierung ging: Ich benutzte ja nur den [0] teil des arrays. Na super. Dann wird fwrite() wohl funktionieren. Hattest Recht sheel, wie immer

    Also folgendes:
    Code c:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    FILE* target = fopen(path,"wb");
        FILE* f = fopen(Obj1,"rb");
        if(f == NULL) return -1;
        unsigned long i = 0;
        unsigned long j = 0;
        char temp[1024];
        while(fgetc(f) != EOF) i++;
        printf("Dateigroesse: %d\n",i);
        fprintf(target,"%d:",i);
        
        char t[256];
        itoa(i,t,10);
        while(j < i)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,1024,1,f);
            fseek(target,j + strlen(t) + 1,SEEK_SET);
            fwrite(temp,1024,1,target);
            j++;
        }
        fclose(f);
    Funktioniert nicht. Auch sheels Bespiel nicht. Aber mit der 1 Zeichen Technik problemlos...
    Geändert von cwriter (15.10.11 um 14:01 Uhr)
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  10. #10
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Hi
    Zitat Zitat von cwriter Beitrag anzeigen
    Funktioniert nicht.
    Was heißt denn das jetzt? Absturz? Ungültige Daten drin? Nicht vollständig geschrieben?

    Grundsätzlich, bei I/O Operationen, ist es eine gute Idee eine Schleife zu bauen, die direkt von dem Erfolg der I/O Operation abhängt.

    Du hast da eine Zählschleife, du prüfst keine Fehlercodes. Da kannst du überhaupt nicht sagen ob die Daten richtig gelesen und richtig geschrieben wurden.

    Wenn du die ganze Datei übertragen willst, dann mach doch einfach eine while (fread(...) != NULL) Schleife.

    Warum verwendest du nicht fseek + ftell zur Ermittelung der Dateigröße?

    Warum schiebst du j denn immer nur 1 Zeichen weiter in der Schleife, wenn du (potenziell) 1024 Bytes gelesen hast? Das ist übrigens auch der Fehler: du liest max. 1024 Bytes, prüfst aber nie wieviel überhaupt gelesen wurden und schreibst dann immer alle 1024 Bytes raus...

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  11. #11
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    @deepthroat

    Funktioniert nicht == Falsche Zeichen werden übertragen

    Naja, der funktionierende Code ist:
    Code c:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    char path[256];
        sprintf(path,"%s.xyz",Ziel);
        FILE* target = fopen(path,"wb");
        FILE* f = fopen(Obj1,"rb");
        if(f == NULL) return -1;
        unsigned long i = 0;
        unsigned long j = 0;
        char temp[16];
        while(fgetc(f) != EOF) i++;
        printf("Dateigroesse: %d\n",i);
        fprintf(target,"%d:",i);
        while(j != i)
        {
            fseek(f,j,SEEK_SET);
            fread(temp,1,16,f);
            fprintf(target,"%c",temp[0]);
            j++;
        }
        fclose(f);
    Der geht bis 10KB mit einer annehmbaren Geschwindigkeit. Alles darüber dauert Jahre.
    Warum verwendest du nicht fseek + ftell zur Ermittelung der Dateigröße?
    Weil ich zwei Dateien in eine schreiben möchte. Folgender Syntax:
    Code :
    1
    
    <Bytes_der_ersten_Datei>:<Erste Datei><Zweite Datei>
    Dann will ich die <Bytes_der_ersten...> durcharbeiten, bis die 2. anfängt.
    Und, ja, ich weiss dass es so ein Thema gibt, ich möchte es aber selbst im c-Standard schreiben.

    Was meinst du? Soll ich einen cString per fprintf() und '\0' - Terminierung oder fwrite() schreiben?

    Gruss cwriter
    Geändert von cwriter (17.10.11 um 09:31 Uhr)
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  12. #12
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von cwriter Beitrag anzeigen
    Funktioniert nicht == Falsche Zeichen werden übertragen
    Genauer?
    Zitat Zitat von cwriter Beitrag anzeigen
    Weil ich zwei Dateien in eine schreiben möchte.
    Na und?! Warum kannst du dann nicht fseek+ftell nehmen?
    Zitat Zitat von cwriter Beitrag anzeigen
    Dann will ich die <Bytes_der_ersten...> durcharbeiten
    Soll das heißen du willst alle Bytes aus der ersten Lesen?
    Zitat Zitat von cwriter Beitrag anzeigen
    Was meinst du? Soll ich einen cString per fprintf() und '\0' - Terminierung oder fwrite() schreiben?
    Wenn es binäre Dateien sind auf jeden Fall fwrite.

    Wie sheel schon sagte sind deine ganze fseek in der Schleife ziemlich unnütz. Du mußt doch nur Daten sukzessive lesen und schreiben....

    Gruß
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  13. #13
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    Genauer?
    Endzeichen von cStrings (nicht initialisiert). Ich werde das Problem mal mit '\0' angehen.
    Na und?! Warum kannst du dann nicht fseek+ftell nehmen?
    Kann ich. Werde es mal versuchen. Die fgetc()-Variante gab mir einfach immer einen Eindruck, wie lange es gehen wird.
    Soll das heißen du willst alle Bytes aus der ersten Lesen?
    Es heisst, ich so viele Bytes lesen will, wie die <Bytes_der_ersten_Datei> (unsigned int) gross ist.
    Wenn es binäre Dateien sind auf jeden Fall fwrite.
    Ich bin immer noch verwirrt: Weshalb geht es, einen char zu schreiben, nicht aber einen char*? Oder liegt das nur an der '\0'? Soll ich dann einfach die Werte aus fread() übernehmen?

    Wie sheel schon sagte sind deine ganze fseek in der Schleife ziemlich unnütz. Du mußt doch nur Daten sukzessive lesen und schreiben....
    Ich hatte es mal ohne fseek(). Netterweise hat fread() sich nicht selbstständig vorgearbeitet -> Datei über 200MB.

    Gruss
    cwriter
    Geändert von cwriter (17.10.11 um 10:03 Uhr)
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

  14. #14
    deepthroat deepthroat ist offline Mitglied Diamant
    tutorials.de Premium-User
    Registriert seit
    Jun 2005
    Beiträge
    8.168
    Zitat Zitat von cwriter Beitrag anzeigen
    Endzeichen von cStrings (nicht initialisiert). Ich werde das Problem mal mit '\0' angehen.
    Das ist doch auch nur eine Umgehungslösung. Versuche das Problem zu verstehen und zu beheben.
    Zitat Zitat von cwriter Beitrag anzeigen
    Es heisst, ich so viele Bytes lesen will, wie die <Bytes_der_ersten_Datei> (unsigned int) gross ist.
    Also die komplette Datei. Du mußt also nicht die Bytes zählen.

    Zitat Zitat von cwriter Beitrag anzeigen
    Ich bin immer noch verwirrt: Weshalb geht es, einen char zu schreiben, nicht aber einen char*? Oder liegt das nur an der '\0'?
    Strings sind nunmal \0 terminiert. Wenn in den Daten aus der Datei aber selbst ein \0 Zeichen drin ist funktionieren Stringfunktionen (wie fprintf) nicht mehr, da sie bei dem ersten \0 abbrechen.
    Zitat Zitat von cwriter Beitrag anzeigen
    Ich hatte es mal ohne fseek(). Netterweise hat fread() sich nicht selbstständig vorgearbeitet -> Datei über 200MB.
    Das lag sehr wahrscheinlich an deiner Vorgehensweise (keine Fehlerprüfung!).

    Gruß
    Geändert von deepthroat (17.10.11 um 10:32 Uhr)
     
    If at first you don't succeed, try again. Then quit. No use being a damn fool about it.

  15. #15
    cwriter cwriter ist offline Mitglied Gold
    Registriert seit
    Mar 2010
    Beiträge
    242
    So. Ich habe jetzt mal eure Vorschläge übernommen:
    Code c:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    FILE* target = fopen(path,"wb");
        FILE* f = fopen(Obj1,"rb");
        if(f == NULL) return -1;
        unsigned long i = 0;
        unsigned long j = 0;
        char temp[1];
        fseek (f, 0, SEEK_END);
            i=ftell (f);
        printf("Dateigroesse: %d\n",i);
        fprintf(target,"%d:",i);
     
        while(j != i)
        {
            fread(temp,1,1,f);
            fwrite(temp,1,1,target);
            j++;
        }
        fclose(f);
    Ergebnis: In der Datei Target steht die Grösse von f und Ì. Ì wird 1000 Mal geschrieben. Was mache ich falsch?

    EDIT: Logisch, man sollte halt schon am Anfang beginnen zu lesen

    Soweit, so gut. Wie kann ich jetzt den Durchsatz vergrössern, ohne dass ich nicht initialisierte chars schreibe?
    Geändert von cwriter (17.10.11 um 10:57 Uhr)
     
    Intel inside - Idiot outside :-)

    Ich schreibe in C und bin Anfänger.
    ______________________________

    Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
    Danke

Ähnliche Themen

  1. Realflow - Programmabsturz
    Von rednik im Forum Sonstige 3D-Programme
    Antworten: 0
    Letzter Beitrag: 08.02.11, 14:29
  2. Array String ]GCC C++} Programmabsturz
    Von jkallup im Forum C/C++
    Antworten: 8
    Letzter Beitrag: 06.07.10, 15:23
  3. Programmabsturz bei Array zuweisung
    Von 3Cyb3r im Forum C/C++
    Antworten: 8
    Letzter Beitrag: 06.03.10, 17:51
  4. Programmabsturz bei Pointern
    Von Manda im Forum C/C++
    Antworten: 14
    Letzter Beitrag: 17.05.09, 00:09
  5. Programmabsturz bei Dreamweaver MX
    Von d4k4 im Forum HTML-Editoren
    Antworten: 1
    Letzter Beitrag: 18.01.03, 09:06

Stichworte