Zitat von
tschloss
Dieses Modul will halt ein File (im Format vcf) als Input. Es gefiel mir einfach nicht, das großeFile häppchenweise in ein kleines umzukopieren. Hätte es lieber über den Speicher gemacht. Aber inzwischen mache ich es über ein tempfile (im Moment 200er-weise).
Thx
Thomas
Genau das meint ich ja, du sollst es in einen Puffer im Speicher laden. Aber ich kenn die Struktur eines vcf nicht (und bin zugegebenermassen da jetzt zu faul mich rein zu lesen und zu denken), ob diese evtl. das ganze extem erschwert oder so. Aber wenn wir mal ein einfaches Format annehmen, dass sequentiell Datensätze hält, dann hätt ich halt in etwa sowas vorgeschlagen (Pseudo-Code):
Code:
$record;
$filehandle;
$databasehandle;
if (!($filehandle = openFile("myfile"))) {
printError("Could not open file!\n");
exit OPEN_FILE;
}
if (!($databasehandle = connectToDatabase("mydatabase"))) {
printError("Could not open database connection!\n");
exit CONN_2_DB;
}
if (!beginDatabaseTransaction($databasehandle)) {
printError("Could not begin database transaction!\n");
exit BEGIN_DB_TRANSACT;
}
while (($record = getRecord($filehandle))) {
if (!saveRecordToDatabase($record)) {
printError("Could not save record to database!\n");
rollBackTransaction($databasehandle);
exit SAVE_2_DB;
}
}
if (!commitDatabaseTransaction($databasehandle)) {
printError("Could not commit database transaction);
exit COMMIT_DB_TRANSACT;
}
closeConnectionToDatabase($databasehandle);
closeFile($filehandle);
print("File successfully imported!");
exit SUCCESS;
In getRecord() ist halt dann das Lesen aus der Datei implementiert und zwar immer ein ganzer Datensatz. Also in einfaches Beispiel wäre immer eine Zeile als Datensatz anzusehen, dann wäre der Umbruch halt das Datensatztrennzeichen bis zu dem man immer alle Zeichen in einen Puffer liest, so etwa (wieder nur Pseudo-Code):
Code:
function getRecord ($fielhandle)
{
#define RECORD_SEP '\n'
$buffer;
$c;
$buffer = "";
while (($c = getc($filehandle))) {
if ($c == RECORD_SEP) {
return $buffer;
}
else {
$buffer .= $c;
}
}
return EOF;
}
Aber natürlich kann die Funktion jegliche andere Logik implementieren einen Satz aus der Datei zu lesen, sei es nach einer Blockgrösse, ggf. auch variabel aus einem Block-Header ermittelt oder nach Schlüsselworten, denkbar wäre hier z. B. XML, lese alles vom nächsten <record> bis zum dazugehörigen </record>, etc., pp....
Oder man lässt das mit der Funktion und schreibts direkt in Code rein (muss man halt den Puffer wieder leeren wenn man den Datensatz in die Datenbank weggespeichert hat), oder, oder, oder...
Sowas ist doch eigentlich das was du wolltest oder, also ohne irgendwelche temporären Dateien?
Zwar läuft das dann natürlich erst mal wegen dem erhöten Aufwand an E/A-Operationen etwas langsamer als wenn du das ganze in einem Rutsch in den Speicher laden würdest, aber bei grossen Dateien belegst du nicht den ganzen physikalischen Speicher wodurch das Betriebssystem anfängt auzulagern und du dann natürlich E/A auf die Platte doppelt und dreifach hast der den Prozess ausbremst (und alle anderen Prozesse ringsherum u. U. auch noch mit runtergezogen werden)...
Lesezeichen