mozilla
Your Search Results

    File I/O

    This article is in need of a technical review.

    Use of OS.File is preferred over the examples in this article. Only use these legacy interfaces if OS.File is not available to you.

    This article describes local file input/output in chrome JavaScript.

    You access the file system using Mozilla XPCOM components.

    Note: File objects are nsIFile. For legacy reasons, there is also an nsILocalFile interface.

    Creating an nsIFile object

    Components.utils.import("resource://gre/modules/FileUtils.jsm");
    
    var file = new FileUtils.File("/home");
    

    Or the same without using FileUtils.jsm:

    var file = Components.classes["@mozilla.org/file/local;1"].
               createInstance(Components.interfaces.nsILocalFile);
    file.initWithPath("/home");
    

    Note: The path should be in the "native" form (for example"C:\\Windows"). If you need to use file:// URIs as initializers, see discussion of nsIIOService below.

    Note: You can still get a file object even if the specified file does not exist, and no exception will be thrown. An exception is thrown only when methods that require the file to exist are called, e.g., isDirectory(), moveTo(), and so on.

    Getting files in special directories

    Components.utils.import("resource://gre/modules/FileUtils.jsm");
    
    // get the "data.txt" file in the profile directory
    var file = FileUtils.getFile("ProfD", ["data.txt"]);
    

    Or the same without using FileUtils.jsm:

    // Get profile directory.
    var file = Components.classes["@mozilla.org/file/directory_service;1"].
               getService(Components.interfaces.nsIProperties).
               get("ProfD", Components.interfaces.nsIFile);
    // Or using Services.jsm and Ci = Components.interfaces
    var file = Services.dirsvc.get("ProfD", Ci.nsIFile);
    
    // Append the file name.
    file.append("data.txt");
    
    // Note: "file" is an object that implements nsIFile. If you want the
    // file system path, use file.path
    

    Note: file is an object that implements nsIFile. If you want the file system path, use file.path,
    .

    Here are some of the special locations the directory service supports:

    String Meaning
    AChrom %CurProcD%/chrome
    APlugns %CurProcD%/plugins
    ComsD %CurProcD%/components
    CurProcD Current working directory (usually the application's installation directory).
    DefProfRt The root of the default profile directory (for example /root/.mozilla).
    DefRt %CurProcD%/defaults
    Desk The user's desktop directory (for example ~/Desktop on Linux or Mac OS X, C:\Documents and Settings\username\Desktop on Windows).
    DfltDwnld The default Downloads directory (for example, ~/Downloads on Mac OS X).
    Home The user's home directory (for example, /home/username).
    PrfDef %installation%/defaults/pref
    ProfD The profile directory.
    ProfDefNoLoc %installation%/defaults/profile
    ProfLD Local Settings on Windows; where the network cache and fastload files are stored.
    Progs User Start menu programs directory (for example, C:\Documents and Settings\username\Start Menu\Programs). This is a Windows-specific value.
    TmpD The operating system's temporary files directory (for example, /tmp on Mac OS X and Linux).
    UChrm The user chrome directory in their profile: %profile%/chrome.
    resource:app The application directory in an XULRunner application.

    Look in the source for other strings available:

    Enumerating drives on Windows

    While you can use initWithPath("/") on UNIX-like systems (Linux, Mac) to get the root of the file system, there's no such root on Windows. However, you can enumerate available drives using the following code:

    Components.utils.import("resource://gre/modules/FileUtils.jsm");
    
    var root = new FileUtils.File("\\\\.");
    var drivesEnum = root.directoryEntries, drives = [];
    while (drivesEnum.hasMoreElements()) {
      drives.push(drivesEnum.getNext().
        QueryInterface(Components.interfaces.nsILocalFile).path);
    }
    

    Creating Folders

    FileUtils.getDir() can create a folder automatically if it doesn't exist yet:

    Components.utils.import("resource://gre/modules/FileUtils.jsm");
    
    var dir = FileUtils.getDir("ProfD", ["DIR"], true);
    

    The above example creates a folder called "DIR" in the user's profile folder. You can also create a directory explicitly; for more information refer to nsIFile.create().

    Creating temporary files

    To create a temporary file, use nsIFile.createUnique():

    Components.utils.import("resource://gre/modules/FileUtils.jsm");
    
    var file = FileUtils.getFile("TmpD", ["suggestedName.tmp"]);
    file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
    // do whatever you need to the created file
    alert(file.path);
    

    User input via nsIFilePicker

    The file picker component, nsIFilePicker, can be used to open standard Open / Save dialogs. It returns the user-specified file as nsIFile.

    nsIFile and path strings

    You can use nsIFile.path to get a platform-specific path string, for example "C:\Windows\System32" or "/usr/share".

    To get a URL of a file, use nsIIOService.newFileURI():

    // file is nsIFile
    Components.utils.import("resource://gre/modules/Services.jsm");
    var url = Services.io.newFileURI(file);
    // url is a nsIURI; to get the string "file://...", see url.spec
    

    To get an nsIFile from the 'file://' URL, use nsIFileURL:

    // url is a nsIURI; see nsIIOService::newURI for getting a string into a nsIURI.
    var file = url.QueryInterface(Components.interfaces.nsIFileURL).file;
    // file is a nsIFile
    

    To load from file://, http://, chrome://, resource:// and other URLs directly, use XMLHttpRequest or NetUtil.asyncFetch().

    Also note that generally you don't need to use nsIFile::path. Use nsIFile directly wherever possible. An example below shows how you should save a path in user prefs.

    Storing nsIFile in preferences

    The following two snippets show the right way to store a file path in user preferences (more about preferences in Mozilla):

    Absolute path (nsIFile)

    To store an arbitrary path in user preferences, use this code:

    // |file| is nsILocalFile. Uses Services.jsm.
    // 1. Write path to prefs
    var prefs = Services.prefs.getBranch("extensions.myext.");
    prefs.setComplexValue("filename", Components.interfaces.nsIFile, file);
    
    // 2. Read path from prefs
    var file = prefs.getComplexValue("filename", Components.interfaces.nsILocalFile);
    

    Relative path (nsIRelativeFilePref)

    To store paths relative to one of the predefined folders listed above, for example file relative to profile folder, use the following code:

    // 1. Write to prefs
    var relFile = Components.classes["@mozilla.org/pref-relativefile;1"].
                  createInstance(Components.interfaces.nsIRelativeFilePref);
    relFile.relativeToKey = "ProfD"; // or any other string listed above
    relFile.file = file;             // |file| is nsILocalFile
    prefs.setComplexValue("filename", 
         Components.interfaces.nsIRelativeFilePref, relFile);
    
    // 2. Read from prefs
    var value = prefs.getComplexValue("filename", 
         Components.interfaces.nsIRelativeFilePref);
    // |value.file| is the file.
    

    Get a file in given directory

    Let us assume an nsIFile file is pointing to some directory (for example a user profile directory). Then you may use file.append("myfile.txt"); to make it point to myfile.txt inside that directory.

    Note: Avoid using dir.path+"\\"+"myfile.txt", as it is not cross-platform at all. Using something like ((path.search(/\\/) != -1) ? path + "\\" : path + "/") + "myfile.txt"; is possible, but nsIFile.append() is much easier to read and is guaranteed to work on all platforms.

    Enumerating files in given directory

    The snippet below makes an array of nsIFiles corresponding to sub-directories/"sub-files" of the given directory. You can tell files from folders by calling nsIFile.isDirectory() and nsIFile.isFile() methods on each entry.

    // file is the given directory (nsIFile)
    var entries = file.directoryEntries;
    var array = [];
    while(entries.hasMoreElements()) {
      var entry = entries.getNext();
      entry.QueryInterface(Components.interfaces.nsIFile);
      array.push(entry);
    }
    

    Reading from a file

    Read into a stream or a string

    This will allow you to read a file without locking up the UI thread while reading. Please note that some I/O, such as getting file information and opening the file can still happen on the main thread and therefore block the UI for periods of time. This sample code uses NetUtil.jsm. So therefore for the first parameter, file, you can pass an nsIFile object or a string (such as a jar path) See: NetUtil.asyncFetch:

    Components.utils.import("resource://gre/modules/NetUtil.jsm");
    
    NetUtil.asyncFetch(file, function(inputStream, status) {
      if (!Components.isSuccessCode(status)) {
        // Handle error!
        return;
      }
    
      // The file data is contained within inputStream.
      // You can read it into a string with
      var data = NetUtil.readInputStreamToString(inputStream, inputStream.available());
    });
    

    Read with content type hint

    It's useful to provide a content type hint to prevent the file system from doing a potentially expensive content type look up (which would be synchronous I/O). In this case an nsIChannel object has to be explicitly created from the file:

    Components.utils.import("resource://gre/modules/NetUtil.jsm");
    // Content type hint is useful on mobile platforms where the filesystem
    // would otherwise try to determine the content type.
    var channel = NetUtil.newChannel(file);
    channel.contentType = "application/json";
    
    NetUtil.asyncFetch(channel, function(inputStream, status) {
      ...
    });
    

    Writing to a file

    Write a string

    This sample uses NetUtil.jsm and FileUtils.jsm.

    Components.utils.import("resource://gre/modules/NetUtil.jsm");
    Components.utils.import("resource://gre/modules/FileUtils.jsm");
    
    // file is nsIFile, data is a string
    
    // You can also optionally pass a flags parameter here. It defaults to
    // FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE;
    var ostream = FileUtils.openSafeFileOutputStream(file);
    
    var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].
                    createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
    converter.charset = "UTF-8";
    var istream = converter.convertToInputStream(data);
    
    // The last argument (the callback) is optional.
    NetUtil.asyncCopy(istream, ostream, function(status) {
      if (!Components.isSuccessCode(status)) {
        // Handle error!
        return;
      }
    
      // Data has been written to the file.
    });
    

    Copy a stream to a file

    This function copies all of the data from an input stream to a file asyncronously. It overwrites the file if it is there, and if it is not there it creates a file then writes into it. It takes an nsIInputStream and an nsIFile as arguments, and uses NetUtil.jsm and FileUtils.jsm. The callback argument is optional.

    function StreamToFile(stream, file, callback) {
        var output = FileUtils.openSafeFileOutputStream(file)
        NetUtil.asyncCopy(stream, output, callback);
    }
    

    Synchronous

    Checking the existence of a file

    Warning: Performing synchronous IO on the main thread can cause serious performance problems. As a result, using this method on the main thread is strongly discouraged!

    // |file| is nsIFile
    if (file.exists()) {
      // ...
    }
    

    Note: You should avoid checking the existence of a file, not only because of the synchronous I/O on the main thread this causes. There might be races between different processes and/or threads, e.g., a file could be immediately created or deleted after you check the existence but before you can perform any other actions such as opening the file for reading or writing.

    Reading a file

    Warning: Performing synchronous IO on the main thread can cause serious performance problems. As a result, using this method on the main thread is strongly discouraged!

    // |file| is nsIFile
    var data = "";
    var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                  createInstance(Components.interfaces.nsIFileInputStream);
    var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
                  createInstance(Components.interfaces.nsIConverterInputStream);
    fstream.init(file, -1, 0, 0);
    cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish
    
    let (str = {}) {
      let read = 0;
      do { 
        read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value
        data += str.value;
      } while (read != 0);
    }
    cstream.close(); // this closes fstream
    
    alert(data);

    Reading Line by Line

    Warning: Performing synchronous IO on the main thread can cause serious performance problems. As a result, using this method on the main thread is strongly discouraged!

    NOTE: The sample code below does not handle text with non-ASCII characters. See Reading textual data details on how to read text from other character sets.
    // open an input stream from file
    var istream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                  createInstance(Components.interfaces.nsIFileInputStream);
    istream.init(file, 0x01, 0444, 0);
    istream.QueryInterface(Components.interfaces.nsILineInputStream);
    
    // read lines into array
    var line = {}, lines = [], hasmore;
    do {
      hasmore = istream.readLine(line);
      lines.push(line.value); 
    } while(hasmore);
    
    istream.close();
    
    // do something with read data
    alert(lines);
    

    Reading a Binary File

    Warning: Performing synchronous IO on the main thread can cause serious performance problems. As a result, using this method on the main thread is strongly discouraged!

    For instance, to get the data in a PNG file:

    var ios = Components.classes["@mozilla.org/network/io-service;1"].
              getService(Components.interfaces.nsIIOService);
    var url = ios.newURI(aFileURL, null, null);
    
    if (!url || !url.schemeIs("file")) throw "Expected a file URL.";
    
    var pngFile = url.QueryInterface(Components.interfaces.nsIFileURL).file;
    
    var istream = Components.classes["@mozilla.org/network/file-input-stream;1"].
                  createInstance(Components.interfaces.nsIFileInputStream);
    istream.init(pngFile, -1, -1, false);
    
    var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
                  createInstance(Components.interfaces.nsIBinaryInputStream);
    bstream.setInputStream(istream);
    
    var bytes = bstream.readBytes(bstream.available());
    

    Writing a File

    Warning: Performing synchronous IO on the main thread can cause serious performance problems. As a result, using this method on the main thread is strongly discouraged!

    // file is nsIFile, data is a string
    var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
                   createInstance(Components.interfaces.nsIFileOutputStream);
    
    // use 0x02 | 0x10 to open file for appending.
    foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0); 
    // write, create, truncate
    // In a c file operation, we have no need to set file mode with or operation,
    // directly using "r" or "w" usually.
    
    // if you are sure there will never ever be any non-ascii text in data you can 
    // also call foStream.write(data, data.length) directly
    var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
                    createInstance(Components.interfaces.nsIConverterOutputStream);
    converter.init(foStream, "UTF-8", 0, 0);
    converter.writeString(data);
    converter.close(); // this closes foStream
    
    Note: The file status flags used in the nsIFileOutputStream.init() function are documented in PR_Open. For more information refer directly to nsprpub/pr/include/prio.h

    Writing a Binary File

    Warning: Performing synchronous IO on the main thread can cause serious performance problems. As a result, using this method on the main thread is strongly discouraged!

    For example, here we can write PNG data to a file.

    // pngBinary already exists
    var aFile = Components.classes["@mozilla.org/file/local;1"].
                createInstance(Components.interfaces.nsILocalFile);
    
    aFile.initWithPath( "/tmp/mypicture.png" );
    aFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0600);
                
    var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"].
                 createInstance(Components.interfaces.nsIFileOutputStream);
    stream.init(aFile, 0x04 | 0x08 | 0x20, 0600, 0); // readwrite, create, truncate
                
    stream.write(pngBinary, pngBinary.length);
    if (stream instanceof Components.interfaces.nsISafeOutputStream) {
        stream.finish();
    } else {
        stream.close();
    
    }
    

    More

    There are more methods and properties on nsIFile and nsILocalFile interfaces; please refer to their documentation for more details. Those methods/properties are mostly self-explanatory, so we haven't included examples of using them here.

    Hide Sidebar