-
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:
dauert das halt bei grossen Dateien ewig. Deshalb wollte ich das ganze ein wenig beschleunigen:Code c:
Resultat: Programmabsturz. Was mache ich falsch?Code c:
Gruss
cwriterIntel 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
-
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
Ungetestet.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...
Gruß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, ...?
-
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
cwriterIntel 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
-
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, ...?
-
Ok, geht nun doch nicht. Dafür gibt's eine andere Fehlermeldung. Juchu

Weisst du etwas? Code:Code :1 2
fread: Expression: num <= (SIZE_MAX / elementSize)
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
cwriterGeä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
-
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 100KBNetiquette (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, ...?
-
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
cwriterIntel 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
-
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...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, ...?
-
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:
Funktioniert nicht. Auch sheels Bespiel nicht. Aber mit der 1 Zeichen Technik problemlos...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);
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
-
17.10.11 08:39 #10
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
HiWas 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.
-
@deepthroat
Funktioniert nicht == Falsche Zeichen werden übertragen
Naja, der funktionierende Code ist:
Der geht bis 10KB mit einer annehmbaren Geschwindigkeit. Alles darüber dauert Jahre.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);
Weil ich zwei Dateien in eine schreiben möchte. Folgender Syntax:Warum verwendest du nicht fseek + ftell zur Ermittelung der Dateigröße?
Dann will ich die <Bytes_der_ersten...> durcharbeiten, bis die 2. anfängt.Code :1
<Bytes_der_ersten_Datei>:<Erste Datei><Zweite Datei>
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 cwriterGeä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
-
17.10.11 09:48 #12
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Genauer?
Na und?! Warum kannst du dann nicht fseek+ftell nehmen?
Soll das heißen du willst alle Bytes aus der ersten Lesen?
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.
-
Endzeichen von cStrings (nicht initialisiert). Ich werde das Problem mal mit '\0' angehen.Genauer?
Kann ich. Werde es mal versuchen. Die fgetc()-Variante gab mir einfach immer einen Eindruck, wie lange es gehen wird.Na und?! Warum kannst du dann nicht fseek+ftell nehmen?
Es heisst, ich so viele Bytes lesen will, wie die <Bytes_der_ersten_Datei> (unsigned int) gross ist.Soll das heißen du willst alle Bytes aus der ersten Lesen?
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?Wenn es binäre Dateien sind auf jeden Fall fwrite.
Ich hatte es mal ohne fseek(). Netterweise hat fread() sich nicht selbstständig vorgearbeitet -> Datei über 200MB.Wie sheel schon sagte sind deine ganze fseek in der Schleife ziemlich unnütz. Du mußt doch nur Daten sukzessive lesen und schreiben....
Gruss
cwriterGeä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
-
17.10.11 10:19 #14
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Das ist doch auch nur eine Umgehungslösung. Versuche das Problem zu verstehen und zu beheben.
Also die komplette Datei. Du mußt also nicht die Bytes zählen.
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.
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.
-
So. Ich habe jetzt mal eure Vorschläge übernommen:
Ergebnis: In der Datei Target steht die Grösse von f und Ì. Ì wird 1000 Mal geschrieben. Was mache ich falsch?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);
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
-
Realflow - Programmabsturz
Von rednik im Forum Sonstige 3D-ProgrammeAntworten: 0Letzter Beitrag: 08.02.11, 14:29 -
Array String ]GCC C++} Programmabsturz
Von jkallup im Forum C/C++Antworten: 8Letzter Beitrag: 06.07.10, 15:23 -
Programmabsturz bei Array zuweisung
Von 3Cyb3r im Forum C/C++Antworten: 8Letzter Beitrag: 06.03.10, 17:51 -
Programmabsturz bei Pointern
Von Manda im Forum C/C++Antworten: 14Letzter Beitrag: 17.05.09, 00:09 -
Programmabsturz bei Dreamweaver MX
Von d4k4 im Forum HTML-EditorenAntworten: 1Letzter Beitrag: 18.01.03, 09:06



4Danke

Zitieren


Login






