Start · Sprachen · JavaScript · Referenz · FileSystemFileEntry.createWriter()

FileSystemFileEntry.createWriter()

Methode

Erzeugt asynchron ein <code>FileWriter</code>-Objekt, mit dem Daten in die Datei geschrieben werden können, die zu diesem <code>FileSystemFileEntry</code> gehört.

seit JavaScript Nicht standardisiert, veraltet – nur Chromium-basi deprecated seit ja Kategorie: webapi

Signatur

FileSystemFileEntry.createWriter(successCallback, errorCallback)

Beschreibung

Die Methode createWriter() gehört zur älteren File and Directory Entries API und gibt über einen Callback ein FileWriter-Objekt zurück. Damit kann man in die Datei schreiben, auf die der Eintrag verweist, darin mit seek() springen und sie mit truncate() kürzen oder verlängern. Das Ergebnis kommt nicht direkt als Rückgabewert und auch nicht als Promise, sondern nur über den übergebenen successCallback.

Einen beschreibbaren Eintrag bekommt man in der Praxis nur aus einem sandboxed Dateisystem, das man mit window.webkitRequestFileSystem() anfordert. Einträge aus Drag & Drop (DataTransferItem.webkitGetAsEntry()) oder aus <input type="file" webkitdirectory> kann man nur lesen. Dort schlägt createWriter() fehl oder steht gar nicht erst zur Verfügung.

FileWriter schreibt asynchron und ereignisbasiert. Jede Operation (write(), truncate()) löst unter anderem writeend oder error aus. Während eine Operation läuft, darf keine zweite starten, sonst gibt es einen InvalidStateError. Mehrere Schreibvorgänge muss man deshalb nacheinander ausführen, zum Beispiel indem man den nächsten erst in onwriteend startet.

Für neue Projekte sollte man die moderne File System API verwenden: FileSystemFileHandle.createWritable() (Origin Private File System über navigator.storage.getDirectory() oder showSaveFilePicker()). Sie arbeitet mit Promises und Streams.

Parameter

Name Typ Default Beschreibung
$successCallback Pflicht (writer: FileWriter) => void Wird mit dem erzeugten FileWriter aufgerufen, sobald der Writer bereit ist.
$errorCallback (error: DOMException | FileError) => void Wird aufgerufen, wenn kein Writer erzeugt werden kann, z. B. weil die Datei fehlt (NotFoundError), der Zugriff verweigert wird (SecurityError) oder der Eintrag schreibgeschützt ist.

Rückgabewert

Typ
void
Beschreibung
Kein direkter Rückgabewert. Der FileWriter wird an successCallback übergeben.

Beispiele

Textdatei im Sandbox-Dateisystem anlegen und beschreiben

const onError = (err) => console.error('Fehler:', err.name, err.message);

window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024, (fs) => {
  fs.root.getFile('notizen.txt', { create: true }, (fileEntry) => {
    fileEntry.createWriter((writer) => {
      writer.onwriteend = () => console.log('Geschrieben, Länge:', writer.length);
      writer.onerror = (e) => console.error('Schreibfehler:', e.target.error);

      const blob = new Blob(['Hallo Welt!\n'], { type: 'text/plain' });
      writer.write(blob);
    }, onError);
  }, onError);
}, onError);
Geschrieben, Länge: 12

Promise-Wrapper und Daten ans Dateiende anhängen

// Callback-API in Promises verpacken
const getWriter = (fileEntry) =>
  new Promise((resolve, reject) => fileEntry.createWriter(resolve, reject));

const writeBlob = (writer, blob) =>
  new Promise((resolve, reject) => {
    writer.onwriteend = resolve;
    writer.onerror = () => reject(writer.error);
    writer.write(blob);
  });

const appendLog = async (fileEntry, line) => {
  const writer = await getWriter(fileEntry);
  writer.seek(writer.length); // ans Ende springen
  await writeBlob(writer, new Blob([`${new Date().toISOString()} ${line}\n`]));
  console.log('Neue Dateigröße:', writer.length);
};

// Aufruf, z. B.: await appendLog(fileEntry, 'App gestartet');
Neue Dateigröße: 38

Datei leeren und danach neu schreiben (sequenziell)

const overwrite = (fileEntry, text) => {
  fileEntry.createWriter((writer) => {
    let truncated = false;
    writer.onwriteend = () => {
      if (!truncated) {
        truncated = true;
        // erst nach Abschluss von truncate() schreiben
        writer.write(new Blob([text], { type: 'text/plain' }));
      } else {
        console.log('Datei ersetzt:', writer.length, 'Bytes');
      }
    };
    writer.onerror = () => console.error(writer.error);
    writer.truncate(0);
  }, (err) => console.error(err));
};

// overwrite(fileEntry, 'Neuer Inhalt');
Datei ersetzt: 12 Bytes

Moderne Alternative: FileSystemFileHandle.createWritable()

const root = await navigator.storage.getDirectory(); // Origin Private File System
const handle = await root.getFileHandle('notizen.txt', { create: true });
const writable = await handle.createWritable();
await writable.write('Hallo Welt!\n');
await writable.close();

const file = await handle.getFile();
console.log(await file.text());
Hallo Welt!

// Wichtig · Fallstricke

  • Nicht standardisiert und veraltet: createWriter() und FileWriter gibt es nur in Chromium-basierten Browsern (Chrome, Edge, Opera) und nur zusammen mit webkitRequestFileSystem(). Firefox und Safari unterstützen zwar FileSystemFileEntry (nur lesend über file()), createWriter() aber nicht. Vor der Nutzung sollte man die Funktion prüfen: typeof entry.createWriter === 'function'.
  • Kein Schreibzugriff auf Dateien des Nutzers: Einträge aus Drag & Drop oder aus Dateiauswahl-Dialogen sind schreibgeschützt. Man kann nur in das sandboxed Dateisystem des eigenen Origins schreiben.
  • Keine parallelen Operationen: Ruft man write() oder truncate() auf, während noch ein Vorgang läuft (readyState === FileWriter.WRITING), gibt es einen InvalidStateError. Der nächste Aufruf gehört in onwriteend.
  • Überschreiben statt Ersetzen: write() schreibt ab der aktuellen position. Ist der neue Inhalt kürzer, bleiben alte Daten am Ende stehen. Deshalb vorher truncate(0) aufrufen oder mit seek(writer.length) gezielt anhängen.
  • Kontingent: Bei TEMPORARY-Speicher darf der Browser die Daten jederzeit löschen. Wird das Kontingent überschritten, gibt es einen QuotaExceededError.
  • Nur in sicheren Kontexten (HTTPS) zuverlässig. Für neuen Code FileSystemFileHandle.createWritable() oder in Workern createSyncAccessHandle() verwenden.