Dateien (fs)¶
Mit fs liest und schreibt ein Skript Dateien. Alles passiert in einem
geschützten Ordner auf dem Server, der Sandbox. Ein Skript kommt nicht
aus ihr heraus — es kann also keine Systemdateien lesen oder überschreiben.
Pfade beginnen immer mit / und gelten innerhalb der Sandbox:
fs["/berichte/april.txt"]. Was ein Skript dort ablegt, sieht der Betrieb
im Sandbox-Ordner auf dem Server und kann es mit anderen Programmen abholen.
Ausführliches dazu: fs — Dateien in der Sandbox.
Die Beispiele arbeiten im Übungsordner /beispiele/dateien; das letzte
Beispiel räumt ihn auf.
Einsteiger¶
1. Eine Textdatei schreiben¶
writeText legt die Datei an (samt fehlender Ordner) oder überschreibt sie.
fs["/beispiele/dateien/hallo.txt"].writeText("Hallo aus KCForms!\n");
log.info("Datei geschrieben");
2. Eine Textdatei lesen¶
3. Prüfen, ob eine Datei existiert¶
fs["/pfad"] liefert immer ein Datei-Objekt — ob es die Datei wirklich
gibt, sagt exists.
var f = fs["/beispiele/dateien/gibt-es-nicht.txt"];
if (f.exists) {
log.info("Datei vorhanden");
} else {
log.info("Datei fehlt: " + f.path);
}
4. Name und Größe anzeigen¶
var f = fs["/beispiele/dateien/hallo.txt"];
log.info("Name: " + f.name);
log.info("Größe: " + f.size + " Byte");
log.info("Liegt in: " + f.parent.path);
size nur bei vorhandenen Dateien abfragen — sonst gibt es einen Fehler.
5. Kurz und knapp mit text¶
Die Eigenschaft text liest und schreibt wie readText/writeText.
fs["/beispiele/dateien/notiz.txt"].text = "Notiz vom " + new Date().format("dd.MM.yyyy");
log.info(fs["/beispiele/dateien/notiz.txt"].text);
6. Einen Ordner anlegen¶
mkdir(true) legt auch fehlende Zwischenordner an.
var ordner = fs["/beispiele/dateien/2026/april"];
ordner.mkdir(true);
log.info(ordner.directory ? "Ordner da" : "kein Ordner");
7. Den Inhalt eines Ordners auflisten¶
list() liefert alle Einträge eines Ordners.
fs["/beispiele/dateien"].list().forEach(function (e) {
log.info((e.directory ? "[Ordner] " : "") + e.name);
});
8. Eine Datei löschen¶
remove() liefert true, wenn die Datei danach weg ist.
Fortgeschritten¶
9. Eine Zeile an eine Datei anhängen¶
Lesen, Zeile anhängen, zurückschreiben — ein einfaches Protokoll.
var f = fs["/beispiele/dateien/protokoll.txt"];
var bisher = f.exists ? f.readText() : "";
var zeile = new Date().format("dd.MM.yyyy HH:mm:ss") + " " + ctx.user.name + " war hier\n";
f.writeText(bisher + zeile);
log.info(f.readText().split("\n").filter(Boolean).length + " Zeilen im Protokoll");
10. Nur bestimmte Dateien auflisten¶
list nimmt eine Filter-Funktion: nur Einträge, für die sie true sagt.
var txt = fs["/beispiele/dateien"].list(function (e) {
return e.file && e.name.endsWith(".txt");
});
log.info("Textdateien: " + txt.map(function (e) { return e.name; }).join(", "));
11. Eine Datei kopieren¶
fs["/beispiele/dateien/hallo.txt"].copy("/beispiele/dateien/sicherung/hallo-kopie.txt");
if (fs["/beispiele/dateien/sicherung/hallo-kopie.txt"].exists) log.info("Kopie vorhanden");
12. Umbenennen oder verschieben¶
rename bekommt den neuen Pfad — in einem anderen Ordner heißt das
„verschieben".
var f = fs["/beispiele/dateien/sicherung/hallo-kopie.txt"];
f.rename("/beispiele/dateien/archiv/hallo-alt.txt");
log.info(fs["/beispiele/dateien/archiv/hallo-alt.txt"].exists ? "verschoben" : "nicht gefunden");
13. Eindeutige Dateinamen¶
Schreiben mehrere Benutzer gleichzeitig, sollte jede Datei einen eigenen Namen haben — etwa mit Zeitstempel und Benutzer.
var name = "export-" + new Date().format("yyyyMMdd-HHmmss") + "-" + ctx.user.name + ".txt";
var f = fs["/beispiele/dateien/exporte/" + name];
f.writeText("Export von " + ctx.user.name);
log.info("Geschrieben: " + f.path);
14. Umlaute und Zeichensätze¶
Standard ist UTF-8. Für ältere Programme kannst du einen anderen Zeichensatz angeben.
var f = fs["/beispiele/dateien/windows.txt"];
f.writeText("Grüße aus Köln", "windows-1252");
log.info("richtig gelesen: " + f.readText("windows-1252"));
log.info("Bytes: " + f.size); // 14 statt 17 – ein Byte pro Umlaut
15. Daten als JSON speichern und wieder laden¶
JSON.stringify macht aus einem Objekt Text, JSON.parse macht daraus
wieder ein Objekt.
var einstellungen = { farbe: "blau", schrift: 12, zuletzt: new Date().format("yyyy-MM-dd") };
fs["/beispiele/dateien/einstellungen.json"].writeText(JSON.stringify(einstellungen, null, 2));
var geladen = JSON.parse(fs["/beispiele/dateien/einstellungen.json"].readText());
log.info("Farbe: " + geladen.farbe + ", Schrift: " + geladen.schrift);
16. Mit einem Ordner-Objekt arbeiten¶
ordner["/datei"] ist dasselbe wie der volle Pfad — praktisch, wenn du
mehrere Dateien im selben Ordner brauchst.
var ordner = fs["/beispiele/dateien/tage"];
ordner.mkdir(true); // der Ordner muss existieren, bevor du Unterpfade nutzt
["montag", "dienstag", "mittwoch"].forEach(function (tag) {
ordner["/" + tag + ".txt"].writeText("Plan für " + tag);
});
log.info(ordner.list().length + " Dateien in " + ordner.path);
17. Eine Datei als Bytes kopieren¶
Bilder, PDFs und andere Nicht-Text-Dateien liest du mit readBytes und
schreibst sie mit writeBytes.
var quelle = fs["/beispiele/dateien/hallo.txt"];
var ziel = fs["/beispiele/dateien/bytes-kopie.bin"];
ziel.writeBytes(quelle.readBytes());
log.info(ziel.size === quelle.size ? "gleich groß" : "unterschiedlich");
Profi¶
18. Alle Dateien eines Ordnerbaums finden¶
Eine Funktion, die sich für jeden Unterordner selbst aufruft („Rekursion").
function alleDateien(ordner, ergebnis) {
ordner.list().forEach(function (e) {
if (e.directory) alleDateien(e, ergebnis);
else ergebnis.push(e);
});
return ergebnis;
}
var dateien = alleDateien(fs["/beispiele/dateien"], []);
dateien.forEach(function (d) { log.info(d.path + " (" + d.size + " Byte)"); });
log.info(dateien.length + " Dateien insgesamt");
19. Wie viel Platz belegt ein Ordner?¶
function groesse(ordner) {
var summe = 0;
ordner.list().forEach(function (e) {
summe += e.directory ? groesse(e) : e.size;
});
return summe;
}
var bytes = groesse(fs["/beispiele/dateien"]);
log.info("Der Übungsordner belegt " + (bytes / 1024).toFixed(1) + " KB");
20. Eingangsordner abarbeiten¶
Ein typischer Ablauf mit anderen Programmen: Dateien liegen in /eingang,
das Skript verarbeitet jede und verschiebt sie nach /erledigt — oder nach
/fehler, wenn etwas nicht stimmt.
var basis = "/beispiele/dateien/import";
// Übungsdaten bereitlegen
fs[basis + "/eingang/a.txt"].writeText("Menge=5");
fs[basis + "/eingang/b.txt"].writeText("Menge=7");
fs[basis + "/eingang/c.txt"].writeText("kaputt");
var ok = 0, kaputt = 0;
fs[basis + "/eingang"].list(function (e) { return e.file; }).forEach(function (datei) {
var name = datei.name;
try {
var treffer = /^Menge=(\d+)$/.exec(datei.readText().trim());
if (!treffer) throw new Error("unbekanntes Format");
log.info(name + ": Menge " + treffer[1]);
datei.rename(basis + "/erledigt/" + name);
ok++;
} catch (e) {
log.warn(name + ": " + e.message);
datei.rename(basis + "/fehler/" + name);
kaputt++;
}
});
log.info("verarbeitet: " + ok + ", Fehler: " + kaputt);
21. Einstellungen mit Standardwerten laden¶
Fehlt die Datei oder ein Wert darin, gelten Standardwerte. So läuft das Skript auch beim allerersten Mal.
function ladeEinstellungen(pfad, standard) {
var f = fs[pfad];
var gelesen = {};
if (f.exists) {
try { gelesen = JSON.parse(f.readText()); }
catch (e) { log.warn("Einstellungen unlesbar, nehme Standard: " + e.message); }
}
var ergebnis = {};
for (var k in standard) ergebnis[k] = (gelesen[k] !== undefined) ? gelesen[k] : standard[k];
return ergebnis;
}
var cfg = ladeEinstellungen("/beispiele/dateien/config.json", { grenze: 500, empfaenger: "team@beispiel.example" });
log.info("Grenze " + cfg.grenze + ", Empfänger " + cfg.empfaenger);
22. Eine Datei aus der Sandbox verschicken¶
Eine Datei als Anhang an eine E-Mail (siehe auch E-Mail).
var f = fs["/beispiele/dateien/hallo.txt"];
var mp = new mail.MessageMultipart();
mp.addText("Im Anhang die gewünschte Datei.");
mp.addResource(f, "hallo.txt", "text/plain", null);
var msg = new mail.Message();
msg.to = "empfaenger@beispiel.example";
msg.subject = "Datei " + f.name;
msg.content = mp;
mail.send(msg);
23. Eine Sandbox-Datei zum Download anbieten¶
var f = fs["/beispiele/dateien/hallo.txt"];
var url = delivery.deliver(f.readBytes(), { name: f.name, mime: "text/plain" });
view.add(new view.Link(url, f.name + " herunterladen"));
log.info("Link: " + url);
24. Aufräumen¶
var ordner = fs["/beispiele/dateien"];
if (ordner.exists) ordner.remove(true);
log.info("Übungsordner aufgeräumt");
remove(true) löscht ohne Rückfrage
Alles unterhalb des Ordners ist danach weg. Prüfe den Pfad genau, bevor du so ein Skript laufen lässt.