2 Stimmen

OS.File im Firefox SDK Add-on

Dies ist mein erster Versuch, ein Firefox-Add-On zu schreiben.

Ich versuche, eine Textdatei zu lesen, die sich in einem Firefox-Add-On befindet, das ich schreibe.

Ich folge dem Beispiel von MDN

let decoder = new TextDecoder();      // Dieser Dekodierer kann mehrmals wiederverwendet werden
let array = OS.File.read("file.txt"); // Die komplette Datei als Array lesen
let text = decoder.decode(array);     // Dieses Array in Text umwandeln

In meiner main.js habe ich den folgenden Code-Ausschnitt:

Components.utils.import("resource://gre/modules/osfile.jsm");

var pathFile = OS.Path.join("_locales", "en", "messages.json");        

let decoder = new TextDecoder('utf-8');

let promise = OS.File.read(pathFile);        
promise = promise.then(
  function onSuccess(array) {
    return decoder.decode(array);
  },
  function onReject(array) {
    console.log("onReject read: ");
  }            
);

Wenn ich das Add-On mit dem Befehl cfx run ausführe, erhalte ich den folgenden Fehler:

Nachricht: ReferenceError: TextDecoder is not defined

Ich verwende derzeit Firefox 30 und das Firefox-Add-On SDK 1.16.

Sollte ich OS.File in main.js nicht in einem Add-On verwenden?

Sollte ich stattdessen FileUtils verwenden, d.h. Components.utils.import("resource://gre/modules/FileUtils.jsm");?

3voto

nmaier Punkte 31044

Zunächst einmal haben Sie die OS.File für Workers-Dokumente verlinkt. Sie verwenden es nicht in einem Worker (kein new Worker irgendwo), sondern im Hauptthread, daher möchten Sie stattdessen auf OS.File für den Hauptthread-Dokumente verweisen.

SDK-Module erhalten im Moment leider nicht automatisch TextEncoder/TextDecoder. Wie @erikvold vorschlägt, könnten Sie folgendes tun:

const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');

oder es direkt von osfile.jsm bekommen:

const { Cc, Ci, Cu } = require("chrome");
const { OS, TextEncoder, TextDecoder } = Cu.import("resource://gre/modules/osfile.jsm", {});

Nun zurück zu Ihrer ursprünglichen Frage:

Im Allgemeinen kann OS.File in SDK-Add-ons verwendet werden und ist eine gute Möglichkeit, beliebige Dateien im Dateisystem zu lesen/schreiben.

Allerdings sind OS.File, FileUtils, sdk/io/... nicht für das Lesen von Dateien in Ihrem Add-on geeignet, da sich diese Dateien normalerweise nicht direkt im Dateisystem des Benutzers befinden, sondern innerhalb der installierten XPI-Datei (die lediglich eine Zip-Datei ist) und diese APIs es Ihnen ermöglichen, Dateien wortwörtlich zu lesen, aber die Container-Zip-Dateien (XPI) nicht für Sie parsen.

Sie haben jedoch einige Optionen:

  • Der Dateiname deutet darauf hin, dass Sie etwas lokalisiert haben möchten. Das SDK wird mit dem l10n-Modul genau für diesen Zweck geliefert.
  • In dem Ordner data/ Ihres Add-ons befindliche Dateien können auch mit self.data.load() gelesen werden, aber Sie müssen die Daten immer noch decodieren/ parsen.
  • Sie können Dateien, die in Ihrem Add-on (XPI) verpackt sind, mit XMLHttpRequest lesen, das das SDK im net/xhr-Modul zur Verfügung stellt. Als zusätzlichen Bonus kann das XHR-Objekt die Datei für Sie dekodieren und/oder parsen, indem Sie einen entsprechenden .responseType Wert festlegen.

Das Erstellen der URI für XHR ist einfach, wenn sich die zu lesende Datei im data/ Ordner Ihres Add-ons befindet, z.B.

const self = require("sdk/self");
var uri = self.data.url("en/messages.json");
// würde zu data/en/messages.json führen

Ansonsten gibt es keinen offiziellen, unterstützten Weg, URIs zu erhalten, aber das folgende funktioniert z.B. für lib/ (im Moment, könnte aber in Zukunft fehlschlagen).

const self = require("sdk/self");
var uri = self.data.url("../lib/main.js");
// würde zu data/../lib/main.js -> lib/main.js führen

Ihre eigenen Dateien an einem anderen Ort zu platzieren, ist kompliziert, da das SDK nur bestimmte Pfade beim Erstellen des XPI paketiert; im Allgemeinen lib/, data/, locale/ (siehe l10n), chrome/ (siehe XUL-Migrationsleitfaden)

Hier ist ein minimales Beispiel zur Verwendung von XHR (aber denken Sie daran, dass es für die Lokalisierung bereits das l10n-Modul gibt):

const self = require("sdk/self");
const { XMLHttpRequest } = require("sdk/net/xhr");

// Angenommen, data/some.json ist:
// {"abc":123}
var req = new XMLHttpRequest();
req.onload = function() {
  // req.response ist ein Objekt, das das geparste JSON enthält.
  console.log(req.response.abc); // 123
};
req.open("GET", self.data.url("some.json"));
req.responseType = "json";
req.send();

PS: Wenn Sie insbesondere mit OS.File und Versprechen im Allgemeinen arbeiten, erwägen Sie die Verwendung von Task.jsm, das es viel einfacher machen kann, Code zu schreiben und neu zu lesen (zu warten).

2voto

erikvold Punkte 15136

Versuchen Sie

const { Buffer, TextEncoder, TextDecoder } = require('sdk/io/buffer');
const { OS } = require("resource://gre/modules/osfile.jsm");

var pathFile = OS.Path.join("_locales", "de", "messages.json");        

let decoder = new TextDecoder('utf-8');

let promise = OS.File.read(pathFile);        
promise = promise.then(function onSuccess(array) {
  return decoder.decode(array);
}, function onReject(array) {
  console.log("onReject read: ");
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X