8. Juli 2007

(Auch große) BLOB's ins Dateisystem schreiben ...

Recht häufig bekomme ich die Frage, wie man denn einen BLOB ins Dateisystem schreiben kann. BFILE hilft nicht weiter - die kann man nur lesen, nicht schreiben. Fertige Funktionen in DBMS_LOB oder einem anderen Package gibt es nicht - insofern bleiben nur zwei Möglichkeiten:
  • UTL_FILE
  • Java in der Datenbank
Im folgenden ist ein Beispiel für UTL_FILE dargestellt. UTL_FILE kann nur mit RAW oder VARCHAR2 umgehen, also muss der Blob in "Chunks" von 32.000 Byte geschrieben werden ... ist aber nicht wirklich ein Problem:
... geht natürlich auch mit CLOB; anstelle von UTL_RAW.PUT_RAW muss dann allerdings UTL_FILE.PUT und VARCHAR2 anstelle von RAW verwendet werden ...

Kommentare:

flow hat gesagt…

Danke, hat mir sehr weitergeholfen!! :)

swissnic hat gesagt…

Hi, der Ansatz hat mir auch geholfen, hatte aber einige Hürden zu meistern.
utl_file.put lieber nicht einsetzten, da es beim anhängen nach 32767 zeichen einen zeilenumbruch macht.
Also lieber utl_file.put_raw verwenden und daten vorher mit utl_raw.cast_to_raw in raw daten umwandeln.
beim fopen den open_mode "wb" verwenden.
Danach konnte ich auch clobs (xml) sauber exportieren.

Carsten Czarski hat gesagt…

Hallo,

in der Tat - die Anmerkungen sind korrekt: Im PL/SQL Paket LOB_WRITER_PLSQL, welches hier verfügbar ist, sind diese Dinge auch drin ...

Viele Grüße

-Carsten

Gerhard Niggemeier hat gesagt…

nebst 'wb' mußte ich noch folgendes abändern, damit es läuft:

v_amount := (dbms_lob.getlength(p_data) ) - v_position + 1;

An sonsten vielen Dank, der Tipp hat mir sehr weiter geholfen.

Riffer hat gesagt…

Vielen Dank für die gut dokumentierte Lösung. Die Kommentare waren allerdings nicht minder wichtig, denn ich muss extrem große XML-Dateien (im GB Bereich) ausgeben und der Tipp von swissnic war da sehr hilfreich.

Ich schließe mich auch Gerhard Niggemeier an, da ohne dieses "+ 1" das letzte Byte der Ausgabe fehlt. Zusätzlich musste bei mir vPosition mit 0 initialisiert werden! Dieser Fehler steckt übrigens auch noch im kompletten "OS Command" Paket!

Ich habe auch noch eine Frage: Kann es sein, dass Oracle (10.2.0.4) keine Dateien größer als 4 GB beschreiben kann?

Carsten Czarski hat gesagt…

Hallo zusammen,

nach soviel Feedback habe ich die Korrekturen nun auch mal in den Code eingebaut. Vielen Dank an alle!

Zur Frage: Auf welcher Plattform läuft die Datenbank und welche Fehlermeldung kommt ...?

Viele Grüße
-Carsten

Riffer hat gesagt…

Die Plattform ist Windows 2000 Server (also 32 Bit Windows).
Es kommt die Fehlermeldung "Write Error" beim Schreibversuch über die 4 GB Grenze hinaus. Das Dateisystem ist NTFS, das kann also als Problem ausgeschlossen werden.

Carsten Czarski hat gesagt…

Hallo,

habe nachgesehen .. ist ein bekanntes Problem und es wird auch behoben. Mit Metalink-Zugriff kann man es sich unter Bug#7596041
ansehen.

Grüße

-Carsten

Meikel hat gesagt…

Das Package hat mir sehr geholfen. Bei sehr großen Dateien (>4GB) habe ich aber die Variablen v_position und v_amount mit dem Typ integer versehen müssen. weil ansonsten einen Fehler bekommen habe, von wegen Wertebereich.

Gruß
Meikel

Anonym hat gesagt…

Hallo, woran kann es liegen wenn die Dateien auf dem Dateisystem mit falschem Namen abgespeichert werden? Zum Beispiel wird die Datei äöü.txt als äöü.txt abgespeichert. Das Blob hat in der DB den korrekten Namen. Wir verwenden das Java Package von ihnen :-). Das Kommando file_pkg.get_fs_encoding gibt "UTF-8" aus. Haben Sie einen Tipp? Vielen Dank. Grüße Mümin

Carsten Czarski hat gesagt…

Hallo Mümin,

generell würde ich auf Umlaute in den Dateinamen nach Möglichkeit verzichten. Der Grund ist, dass die Datenbank den UTF-8-Zeichensatz verwendet: Alle Strings (auch der Dateiname) werden also UTF-8 kodiert; und diese Kodierung wird auch für den Dateinamen verwendet. Die Prozedur SET_FS_ENCODING setzt zwar intern die Java-Property file.encoding, aber auch das hilft nicht auf allen Plattformen, wie zahlreiche Diskussionsthreads im Internet zeigen; ein Beispiel hier. Das FILE_PKG Paket ist auf die darunterliegende Java-Funktion angewiesen - was diese kann, kann auch FILE_PKG, und was nicht ... das nicht.

Generell empfehle ich, sich bei Dateinamen auf die guten alten ASCII Zeichen zu beschränken - ganz nebenbei verhindert das auch potenzielle Probleme mit anderen Programmen, welche die Dateien gegebenenfalls wieder öffnen müssen ...

Beste Grüße

-Carsten

Beliebte Postings