Datei dynamisch einlesen -> leider lahm
-
Eine gute Strategie ist, den reservierten Block jedes Mal um einen Faktor 2 zu vergrößern. Das verschwendet nicht viel Platz und benötigt im Mittel konstante Zeit (anstatt wie jetzt mit der Dateigröße linear viel Zeit) für das reservieren.
-
SeppJ schrieb:
Eine gute Strategie ist, den reservierten Block jedes Mal um einen Faktor 2 zu vergrößern. Das verschwendet nicht viel Platz und benötigt im Mittel konstante Zeit (anstatt wie jetzt mit der Dateigröße linear viel Zeit) für das reservieren.
ich hör schon meine festplatte swappen
-
int main ( int argc, const char *argv[] ) { FILE *pDataIn = NULL; unsigned __int8 *biosFile = NULL; unsigned __int64 fileSize = NULL; if (fopen_s(&pDataIn, argv[1], "rb")) { perror("Error opening file"); return -1; } while (!feof(pDataIn)) { biosFile = (unsigned __int8 *) realloc(biosFile, sizeof(__int8) + fileSize * 2); fileSize += fread (&biosFile[fileSize], sizeof(__int8), 1 + fileSize / 2, pDataIn); }; fclose ( pDataIn ); return 0; }
So gehts schön schnell
Könnte mir aber vorstellen, dass es so Probleme geben kann, wenn die Dateigröße kein vielfaches von 2 ist.
-
Dateien auf der Platte sind nicht Byteweise sondern Blockweise gespeichert. Du solltest wenigstens in dieser Blockgröße die Datei lesen.
Warum schließt Du aus, die Größe der Datei im Vorfeld zu bestimmen? Ist doch schneller gemacht als Bytes zu schlürfen:
fseek (pDataIn, 0, SEEK_END); size=ftell (pDataIn);
Ciao
MM
-
Warum schließt Du aus, die Größe der Datei im Vorfeld zu bestimmen?
Weil ich mich gefragt habe, ob es eine (mehr oder weniger) praktikable Lösung gibt, die Größenbestimmung und den Einleseprozess in einem Rutsch zu erledigen.
Du solltest wenigstens in dieser Blockgröße die Datei lesen.
Was steckt dahinter ? Und trifft das auch auf SSDs zu ?
-
exilcubaner schrieb:
SeppJ schrieb:
Eine gute Strategie ist, den reservierten Block jedes Mal um einen Faktor 2 zu vergrößern. Das verschwendet nicht viel Platz und benötigt im Mittel konstante Zeit (anstatt wie jetzt mit der Dateigröße linear viel Zeit) für das reservieren.
ich hör schon meine festplatte swappen
Hörst du sie auch, wenn du irgendwelche anderen Programme benutzt? Das ist eine sehr, sehr verbreitete Strategie in den Standardbibliotheken von Programmiersprachen, die lineare, dynamische Containern von Haus aus anbieten (also so ziemlich alle außer C und Assembler). In C muss man sich das dann eben selber machen.
Könnte mir aber vorstellen, dass es so Probleme geben kann, wenn die Dateigröße kein vielfaches von 2 ist.
Irgendeinen Fall maximaler Verschwendung hat man eben. Es ist aber selbst in diesem schlimmsten Ausnahmefall bloß eine Verschwendung von < 50%. Das ist eben der Preis der Geschwindigkeit. Noch schneller wäre natürlich ein größerer Faktor als 2, mit noch mehr potentieller Speicherverschwendung. Ein Faktor zwischen 1 und 2 bewirkt entsprechend das Gegenteil.
Aber: Von 1 MB auf 2 MB, das hat vielleicht einen Rechner vor 15 Jahren gestört. Die hatten aber auch Recht selten 1 MB-Dateien zu bearbeiten.
-
Pyro Phoenix schrieb:
Warum schließt Du aus, die Größe der Datei im Vorfeld zu bestimmen?
Weil ich mich gefragt habe, ob es eine (mehr oder weniger) praktikable Lösung gibt, die Größenbestimmung und den Einleseprozess in einem Rutsch zu erledigen.
Die Größenbestimmung ist kein Einlesevorgang. Um den Dateizeiger an das Ende zu setzen und die Differenz zum Anfang zu berechnen, wird die Datei nicht gelesen. Deine hier gefundene Lösung ist daher eher etwas, wenn man die Größe im Voraus nicht wissen kann (zum Beispiel Nutzereingabe).
-
SeppJ schrieb:
exilcubaner schrieb:
SeppJ schrieb:
Eine gute Strategie ist, den reservierten Block jedes Mal um einen Faktor 2 zu vergrößern. Das verschwendet nicht viel Platz und benötigt im Mittel konstante Zeit (anstatt wie jetzt mit der Dateigröße linear viel Zeit) für das reservieren.
ich hör schon meine festplatte swappen
Hörst du sie auch, wenn du irgendwelche anderen Programme benutzt?
ja, kann schon mal vorkommen! besonders bei solchen, die immer die ganze datei einlesen müssen, noch dazu, wenn sie vorher nicht wissen wie groß das teil eig. ist, welches gewuppt werden soll.
also für mich ist das kind eig. schon an dem punkt in den brunnen gefallen, wo man anfängt, date(n|ien) zu verarbeiten, deren größe man nicht kennt. es dann mit iwelchen techniken zu kompensieren, wiederspricht meiner arbeitsweise!
-
Die Größenbestimmung ist kein Einlesevorgang.
Gut zu wissen. Ich bin bisher immer vom Gegenteil ausgegangen.
Dann schonmal Danke für eure Mithilfe. Wieder was dazugelernt
-
exilcubaner schrieb:
also für mich ist das kind eig. schon an dem punkt in den brunnen gefallen, wo man anfängt, date(n|ien) zu verarbeiten, deren größe man nicht kennt. es dann mit iwelchen techniken zu kompensieren, wiederspricht meiner arbeitsweise!
Man kann seinen Horizont auch künstlich einschränken.
Viele Befehle der *ix-Shells arbeiten so. Denn sonst könnten sie nicht als Filter arbeiten.
-
Pyro Phoenix schrieb:
Weil ich mich gefragt habe, ob es eine (mehr oder weniger) praktikable Lösung gibt, die Größenbestimmung und den Einleseprozess in einem Rutsch zu erledigen.
ja, eine praktikable lösung gibt es, indem du die dateigröße vorher bestimmst
(stat, fstat), fseek ist aus mehreren gründen nicht zu empfehlen.
-
DirkB schrieb:
exilcubaner schrieb:
also für mich ist das kind eig. schon an dem punkt in den brunnen gefallen, wo man anfängt, date(n|ien) zu verarbeiten, deren größe man nicht kennt. es dann mit iwelchen techniken zu kompensieren, wiederspricht meiner arbeitsweise!
Man kann seinen Horizont auch künstlich einschränken.
Viele Befehle der *ix-Shells arbeiten so. Denn sonst könnten sie nicht als Filter arbeiten.so, dann bau mir doch mal schnell einen filter, der alle groß in kleinbuchstaben wandelt. ist eig. ein einzeiler, ohne header und main gedöns. ich würde sagen, wir schauen uns dann deine lösung gemeinsam an und reden über filter
-
exilcubaner schrieb:
DirkB schrieb:
exilcubaner schrieb:
also für mich ist das kind eig. schon an dem punkt in den brunnen gefallen, wo man anfängt, date(n|ien) zu verarbeiten, deren größe man nicht kennt. es dann mit iwelchen techniken zu kompensieren, wiederspricht meiner arbeitsweise!
Man kann seinen Horizont auch künstlich einschränken.
Viele Befehle der *ix-Shells arbeiten so. Denn sonst könnten sie nicht als Filter arbeiten.so, dann bau mir doch mal schnell einen filter, der alle groß in kleinbuchstaben wandelt. ist eig. ein einzeiler, ohne header und main gedöns. ich würde sagen, wir schauen uns dann deine lösung gemeinsam an und reden über filter
cat | tr [:upper:] [:lower:]
-
na super, ich wollte eine c implementation, so dass wir mal sehen, wieviel speicher das tool verbraucht.
-
also bei mir reicht für so einen 'filter' ein char auf dem stack...
if [ ! -e a.out ] ; then echo -e "#include <stdio.h>\n#include <ctype.h>\nint main(){char c;while((c=getchar())!=EOF){putchar(tolower(c));}return 0;}" | gcc -xc - && echo "asdASDasd" | ./a.out && rm a.out; else echo "error a.out file exist"; fi
-
so ists besser
exilcubaner schrieb:
also bei mir reicht für so einen 'filter' ein char auf dem stack...
if [ ! -e a.out ] ; then echo -e "#include <stdio.h>\n#include <ctype.h>\nint main(){char c;while((c=getchar())!=EOF){if(putchar(tolower(c))==EOF)return 1;}return 0;}" | gcc -xc - && echo "asdASDasd" | ./a.out && rm a.out; else echo "error a.out file exist"; fi
-
uiuiui, 'char c' sollte eher ein 'int c' sein... tja, das kommt davon, wenn man die funktionen schon ewig hat ruhen lassen :p