MDN may have intermittent access issues April 18 13:00 - April 19 01:00 UTC. See whistlepig.mozilla.org for all notifications.

mozilla

Revision 39465 of File I/O

  • Revision slug: Code_snippets/File_I//O
  • Revision title: File I/O
  • Revision id: 39465
  • Created:
  • Creator: mmccoo
  • Is current revision? No
  • Comment 13 words added, 12 words removed

Revision Content

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

You access the file system using Mozilla XPCOM components. A list of resources and interfaces for local I/O is available for both Files and Streams at XUL Planet.

Available libraries

There are a few JavaScript wrappers for I/O XPCOM components. See JSLib and io.js (original by MonkeeSage). The io.js module is much smaller and very easy to use (simple examples are included in the module).

Creating a nsIFilee object ("opening" files)

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

NOTE: the path passed to initWithPath() should be in "native" form (e.g. "C:\\Windows"). If you need to use file:// URIs as initializers, see discussion of nsIIOService below.

NOTE: initWithPath() / initWithFile() functions don't throw an exception if the specified file does not exist. An exception is thrown when methods that require the file existence are called, e.g. isDirectory(), moveTo(), etc.

Getting special files

// get profile directory
var file = Components.classes["@mozilla.org/file/directory_service;1"]
                     .getService(Components.interfaces.nsIProperties)
                     .get("ProfD", Components.interfaces.nsIFile);

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

Here are some strings you can put in place of "ProfD" (stolen from MonkeeSage's I/O module comments):

String Meaning
ProfD profile directory
DefProfRt user (e.g., /root/.mozilla)
UChrm  %profile%/chrome
DefRt  %installation%/defaults
PrfDef  %installation%/defaults/pref
ProfDefNoLoc  %installation%/defaults/profile
APlugns  %installation%/plugins
AChrom  %installation%/chrome
ComsD  %installation%/components
CurProcD installation (usually)
Home OS root (e.g., /root)
TmpD OS tmp (e.g., /tmp)
ProfLD Local Settings on windows; where the network cache and fastload files are stored
resource:app application directory in a XULRunner app
Desk Desktop directory (e.g. ~/Desktop on Linux, C:\Documents and Settings\username\Desktop on Windows)
Progs User start menu programs directory (e.g., C:\Documents and Settings\username\Start Menu\Programs)

Look in the Source for other strings available: {{ Source("xpcom/io/nsAppDirectoryServiceDefs.h") }}, {{ Source("xpcom/io/nsDirectoryServiceDefs.h") }}.

Getting your extension's folder

NOTE: This will only work in Firefox/Thunderbird 1.5+, not 1.0.

Via nsIExtensionManager
// the extension's id from install.rdf
var MY_ID = "myextension@my.name";
var em = Components.classes["@mozilla.org/extensions/manager;1"].
         getService(Components.interfaces.nsIExtensionManager);
// the path may use forward slash ("/") as the delimiter
// returns nsIFile for the extension's install.rdf
var file = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "install.rdf");
var filestring = file.path;
From an XPCOM component

To get the directory that an extension is installed in, use an XPCOM component written in JavaScript. The special __LOCATION__ builtin will return an nsIFile of the component file:

extensiondir/component/GetExtensionDirectory.js:

var componentFile = __LOCATION__;
var componentsDir = componentFile.parent;
var extensionDir = componentsDir.parent;

Creating Folders

To create a folder, use nsIFile.create():

var file = Components.classes["@mozilla.org/file/directory_service;1"]
                     .getService(Components.interfaces.nsIProperties)
                     .get("ProfD", Components.interfaces.nsIFile);
file.append("DIR");
if( !file.exists() || !file.isDirectory() ) {   // if it doesn't exist, create
   file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
}

The above example creates a folder called "DIR" in the Profile folder. For more information, refer to the nsIFile.create reference.

Creating temporary files

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

var file = Components.classes["@mozilla.org/file/directory_service;1"]
                     .getService(Components.interfaces.nsIProperties)
                     .get("TmpD", Components.interfaces.nsIFile);
file.append("suggestedName.tmp");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
// 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. The components returns user-specified file as nsIFile.

nsIFile and path strings

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

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

// file is nsIFile
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var URL = ios.newFileURI(file);
// URL is a nsIURI; to get the string, "file://...", see URL.spec

To get a 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 now a nsIFile

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

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 nsILocalFile 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 (nsILocalFile)

To store arbitrary path in user preferences, use this code.

// |file| is nsILocalFile
// 1. Write path to prefs
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                      .getService(Components.interfaces.nsIPrefService)
                      .getBranch("extensions.myext.");
prefs.setComplexValue("filename", Components.interfaces.nsILocalFile, 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.

Navigating with nsIFile

Get a file in given directory

Assume, file is an nsIFile pointing to some directory (f.e. a user profile directory). You can use file.append("myfile.txt"); to make file 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 Mozilla itself works.

Enumerating files in given directory

The snippet below makes an array of nsIFiles corresponding to sub-directories/"sub-files" of 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

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.

Simple

// |file| is nsIFile
var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                        .createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
                        .createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(file, -1, 0, 0);
sstream.init(fstream); 

var str = sstream.read(4096);
var data = "";
while (str.length > 0) {
  data += str;
  str = sstream.read(4096);
}

sstream.close();
fstream.close();
alert(data);

Line by line

// 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);

Asynchronously

This will allow you to read a file without locking up the UI thread.

// |file| is nsIFile
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var fileURI = ios.newFileURI(file);
var channel = ios.newChannelFromURI(fileURI);
var observer = {
  onStreamComplete : function(aLoader, aContext, aStatus, aLength, aResult)
  {
    alert(aResult);
  }
};
var sl = Components.classes["@mozilla.org/network/stream-loader;1"]
                   .createInstance(Components.interfaces.nsIStreamLoader);
sl.init(channel, observer, null);

Binary File

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 to a file

NOTE: This code is not intl-aware. Writing non-ASCII characters will not work correctly. See Writing textual data for intl-aware code.

// 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.
foStream.write(data, data.length);
foStream.close();

NOTE: The file status flags used in the nsIFileOutputStream::init() function are documented in PR_Open. For more information refer directly to {{ Source("nsprpub/pr/include/prio.h") }}

Writing a Binary File

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, 600);
            
var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"]
                       .createInstance(Components.interfaces.nsIFileOutputStream);
stream.init(aFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate
            
stream.write(pngBinary, pngBinary.length);
if (stream instanceof Components.interfaces.nsISafeOutputStream) {
    stream.finish();
} else {
    stream.close();
}

Copy a stream to a file

This function returns a basic stream listener that copies all of the data from an input stream to a file. Takes an nsIFile as an argument, which is assumed to be open and created; depending on what you're doing, you might prefer to create the file in onStartRequest and close it in onStopRequest.

function StreamToFile(file)
{
    var output = Components.classes["@mozilla.org/network/file-output-stream;1"]
                           .createInstance(Components.interfaces.nsIFileOutputStream);
    var buffer = Components.classes["@mozilla.org/network/buffered-output-stream;1"]
                           .createInstance(Components.interfaces.nsIBufferedOutputStream);
    output.init(file, 0x02 | 0x08 | 0x20, 0664, null);
    buffer.init(output, 8192);

    return {
        onStartRequest: function(request, context) { },

        onDataAvailable: function onDataAvailable(request, context, stream, offset, count)
        {
            while(count > 0)
                count -= buffer.writeFrom(stream, count);
        },

        onStopRequest: function(request, context) { }
    };
}

More

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

{{ languages( { "fr": "fr/Extraits_de_code/Fichiers_E//S", "ja": "ja/Code_snippets/File_I//O", "pl": "pl/Fragmenty_kodu/Plik_I//O" } ) }}

Revision Source

<p>This article describes local file input/output in chrome JavaScript.</p>
<p>You access the file system using Mozilla <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> components. A list of resources and interfaces for local I/O is available for both <a class="external" href="http://www.xulplanet.com/references/xpcomref/group_Files.html">Files</a> and <a class="external" href="http://www.xulplanet.com/references/xpcomref/group_Streams.html">Streams</a> at <a class="external" href="http://www.xulplanet.com/">XUL Planet</a>.</p>
<h3 name="Available_libraries">Available libraries</h3>
<p>There are a few JavaScript wrappers for I/O XPCOM components. See <a class="external" href="http://jslib.mozdev.org/">JSLib</a> and <a href="/en/io.js" title="en/io.js">io.js</a> (original by <a class="external" href="http://gratisdei.com/io.js">MonkeeSage</a>). The io.js module is much smaller and very easy to use (simple examples are included in the module).</p>
<h3 name="Creating_a_file_object_.28.22opening.22_files.29">Creating a nsIFile<span class="Apple-style-span" style="color: rgb(37, 34, 29); font-family: 'Courier New'; font-size: 12px; line-height: normal; white-space: pre; "><span class="Apple-style-span" style="color: rgb(43, 39, 32); font-family: Georgia; font-size: 21px; line-height: 35px; white-space: normal; "><span class="Apple-style-span" style="color: rgb(37, 34, 29); font-family: 'Courier New'; font-size: 12px; line-height: normal; white-space: pre; "><span class="Apple-style-span" style="color: rgb(43, 39, 32); font-family: Georgia; font-size: 21px; line-height: 35px; white-space: normal; ">e object ("opening" files)</span></span></span></span></h3>
<pre>var file = Components.classes["@mozilla.org/file/local;1"]
                     .createInstance(Components.interfaces.nsILocalFile);
file.initWithPath("/home");
</pre>
<div class="note">
<p><strong>NOTE</strong>: the path passed to <code>initWithPath()</code> should be in "native" form (e.g. <code>"C:\\Windows"</code>). If you need to use <a class=" external" href="file://" rel="freelink">file://</a> URIs as initializers, see discussion of <a href="/en/nsIIOService" title="en/nsIIOService">nsIIOService</a> below.</p>
</div>
<div class="note">
<p><strong>NOTE</strong>: <code>initWithPath()</code> / <code>initWithFile()</code> functions don't throw an exception if the specified file does not exist. An exception is thrown when methods that require the file existence are called, e.g. <code>isDirectory()</code>, <code>moveTo()</code>, etc.</p>
</div>
<h3 name="Getting_special_files">Getting special files</h3>
<pre>// get profile directory
var file = Components.classes["@mozilla.org/file/directory_service;1"]
                     .getService(Components.interfaces.nsIProperties)
                     .get("ProfD", Components.interfaces.nsIFile);

// NOTE: "file" is an object that implements nsIFile. If you want the
// file system path, use file.path
</pre>
<p>Here are some strings you can put in place of <code>"ProfD"</code> (stolen from MonkeeSage's I/O module comments):</p>
<table class="standard-table"> <tbody> <tr> <th>String</th> <th>Meaning</th> </tr> <tr> <td>ProfD</td> <td>profile directory</td> </tr> <tr> <td>DefProfRt</td> <td>user (e.g., /root/.mozilla)</td> </tr> <tr> <td>UChrm</td> <td> %profile%/chrome</td> </tr> <tr> <td>DefRt</td> <td> %installation%/defaults</td> </tr> <tr> <td>PrfDef</td> <td> %installation%/defaults/pref</td> </tr> <tr> <td>ProfDefNoLoc</td> <td> %installation%/defaults/profile</td> </tr> <tr> <td>APlugns</td> <td> %installation%/plugins</td> </tr> <tr> <td>AChrom</td> <td> %installation%/chrome</td> </tr> <tr> <td>ComsD</td> <td> %installation%/components</td> </tr> <tr> <td>CurProcD</td> <td>installation (usually)</td> </tr> <tr> <td>Home</td> <td>OS root (e.g., /root)</td> </tr> <tr> <td>TmpD</td> <td>OS tmp (e.g., /tmp)</td> </tr> <tr> <td>ProfLD</td> <td>Local Settings on windows; where the network cache and fastload files are stored</td> </tr> <tr> <td>resource:app</td> <td>application directory in a XULRunner app</td> </tr> <tr> <td>Desk</td> <td>Desktop directory (e.g. ~/Desktop on Linux, C:\Documents and Settings\username\Desktop on Windows)</td> </tr> <tr> <td>Progs</td> <td>User start menu programs directory (e.g., C:\Documents and Settings\username\Start Menu\Programs)</td> </tr> </tbody>
</table>
<p>Look in the Source for other strings available: {{ Source("xpcom/io/nsAppDirectoryServiceDefs.h") }}, {{ Source("xpcom/io/nsDirectoryServiceDefs.h") }}.</p>
<h4 name="Getting_your_extension.27s_folder">Getting your extension's folder</h4>
<div class="note">
<p><strong>NOTE</strong>: This will only work in Firefox/Thunderbird 1.5+, not 1.0.</p>
</div>
<h5 name="Via_nsIExtensionManager">Via <code>nsIExtensionManager</code></h5>
<pre class="eval">// the extension's id from <a href="/en/Install_Manifests" title="en/Install_Manifests">install.rdf</a>
var MY_ID = "<a class=" link-mailto" href="mailto:myextension@my.name" rel="freelink">myextension@my.name</a>";
var em = Components.classes["@mozilla.org/extensions/manager;1"].
         getService(Components.interfaces.nsIExtensionManager);
// the path may use forward slash ("/") as the delimiter
// returns nsIFile for the extension's install.rdf
var file = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "install.rdf");
var filestring = file.path;<br></pre>
<h5 name="From_an_XPCOM_component">From an XPCOM component</h5>
<p>To get the directory that an extension is installed in, use an XPCOM component written in JavaScript. The special <code>__LOCATION__</code> builtin will return an nsIFile of the component file:</p>
<p>extensiondir/component/GetExtensionDirectory.js:</p>
<pre class="eval">var componentFile = __LOCATION__;
var componentsDir = componentFile.parent;
var extensionDir = componentsDir.parent;
</pre>
<h3 name="Creating_Folders">Creating Folders</h3>
<p>To create a folder, use <code>nsIFile.create()</code>:</p>
<pre class="eval">var file = Components.classes["@mozilla.org/file/directory_service;1"]
                     .getService(Components.interfaces.nsIProperties)
                     .get("ProfD", Components.interfaces.nsIFile);
file.append(<em>"DIR"</em>);
if( !file.exists() || !file.isDirectory() ) {   // if it doesn't exist, create
   file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
}
</pre>
<p>The above example creates a folder called <em>"DIR"</em> in the <a class="external" href="http://www.mozilla.org/support/firefox/profile">Profile folder</a>. For more information, refer to the <a href="/en/nsIFile/create" title="en/nsIFile/create"><code>nsIFile.create</code> reference</a>.</p>
<h3 name="Creating_temporary_files">Creating temporary files</h3>
<p>To create a temporary file, use <code>nsIFile.createUnique()</code>:</p>
<pre>var file = Components.classes["@mozilla.org/file/directory_service;1"]
                     .getService(Components.interfaces.nsIProperties)
                     .get("TmpD", Components.interfaces.nsIFile);
file.append("suggestedName.tmp");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
// do whatever you need to the created file
alert(file.path);
</pre>
<h3 name="User_input_via_nsIFilePicker">User input via nsIFilePicker</h3>
<p>The <a href="/en/nsIFilePicker" title="en/nsIFilePicker">file picker component (nsIFilePicker)</a> can be used to open standard Open / Save dialogs. The components returns user-specified file as <code><a href="/en/nsIFile" title="en/nsIFile">nsIFile</a></code>.</p>
<h3 name="nsIFile_and_path_strings">nsIFile and path strings</h3>
<p>You can use <code>nsIFile.path</code> to get platform-specific path string, e.g. <code>"C:\Windows\System32"</code> or <code>"/usr/share"</code>.</p>
<p>To get a URL of a file, use <a href="/en/nsIIOService#newFileURI.28.29" title="en/nsIIOService#newFileURI.28.29">nsIIOService#newFileURI()</a>:</p>
<pre>// file is nsIFile
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var URL = ios.newFileURI(file);
// URL is a nsIURI; to get the string, "file://...", see URL.spec
</pre>
<p>To get a <code>nsIFile</code> from the '<a class=" external" href="file://" rel="freelink">file://</a>' URL, use <a href="/en/NsIFileURL" title="en/NsIFileURL">nsIFileURL</a>:</p>
<pre>// URL is a nsIURI; see nsIIOService::newURI for getting a string into a nsIURI.
var file = URL.QueryInterface(Components.interfaces.nsIFileURL)
              .file;
// file is now a nsIFile
</pre>
<p>To load from <em><a class=" external" href="file://" rel="freelink">file://</a></em>, <em><a class=" external" href="http://" rel="freelink">http://</a></em>, <em><a class=" external" href="chrome://" rel="freelink">chrome://</a></em>, <em><a class=" external" href="resource://" rel="freelink">resource://</a></em> and other URLs directly, use <a href="/en/XMLHttpRequest" title="en/XMLHttpRequest">XMLHttpRequest</a> or <a href="/en/nsIChannel" title="en/nsIChannel">nsIChannel</a> (<a class="external" href="http://forums.mozillazine.org/viewtopic.php?p=921150#921150">example</a>).</p>
<p>Also note that generally you don't need to use <code>nsIFile::path</code>. Use <code>nsIFile</code> directly wherever possible. An example below shows how you should save a path in user prefs.</p>
<h3 name="Storing_nsILocalFile_in_preferences">Storing nsILocalFile in preferences</h3>
<p>The following two snippets show the right way to store a file path in user preferences (<a href="/en/Code_snippets/Preferences" title="en/Code_snippets/Preferences">more about preferences in Mozilla</a>):</p>
<h4 name="Absolute_path_.28nsILocalFile.29">Absolute path (nsILocalFile)</h4>
<p>To store arbitrary path in user preferences, use this code.</p>
<pre>// |file| is nsILocalFile
// 1. Write path to prefs
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                      .getService(Components.interfaces.nsIPrefService)
                      .getBranch("extensions.myext.");
prefs.setComplexValue("filename", Components.interfaces.nsILocalFile, file);

// 2. Read path from prefs
var file = prefs.getComplexValue("filename", Components.interfaces.nsILocalFile);
</pre>
<h4 name="Relative_path_.28nsIRelativeFilePref.29">Relative path (nsIRelativeFilePref)</h4>
<p>To store paths relative to one of the predefined folders listed above, for example file relative to profile folder, use the following code:</p>
<pre>// 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.
</pre>
<h3 name="Navigating_with_nsIFile">Navigating with nsIFile</h3>
<h4 name="Get_a_file_in_given_directory">Get a file in given directory</h4>
<p>Assume, <code>file</code> is an <code>nsIFile</code> pointing to some directory (f.e. a user profile directory). You can use <code>file.append("myfile.txt");</code> to make <code>file</code> point to <code>myfile.txt</code> inside that directory.</p>
<div class="note">
<p><strong>NOTE</strong>: avoid using <code>dir.path+"\\"+"myfile.txt"</code>, as it is not cross-platform at all. Using something like <code>((path.search(/\\/) != -1) ? path + "\\" : path + "/") + "myfile.txt";</code> is possible, but <code>nsIFile.append()</code> is much easier to read and is guaranteed to work on all platforms Mozilla itself works.</p>
</div>
<h4 name="Enumerating_files_in_given_directory">Enumerating files in given directory</h4>
<p>The snippet below makes an array of <code>nsIFile</code>s corresponding to sub-directories/"sub-files" of given directory. You can tell files from folders by calling <code>nsIFile.isDirectory()</code> and <code>nsIFile.isFile()</code> methods on each <code>entry</code>.</p>
<pre>// 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);
}
</pre>
<h3 name="Reading_from_a_file">Reading from a file</h3>
<div class="note">
<p><strong>NOTE</strong>: The sample code below does not handle text with non-ASCII characters. See <a href="/en/Reading_textual_data" title="en/Reading_textual_data">Reading textual data</a> details on how to read text from other character sets.</p>
</div>
<h4 name="Simple">Simple</h4>
<pre>// |file| is nsIFile
var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                        .createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
                        .createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(file, -1, 0, 0);
sstream.init(fstream); 

var str = sstream.read(4096);
var data = "";
while (str.length &gt; 0) {
  data += str;
  str = sstream.read(4096);
}

sstream.close();
fstream.close();
alert(data);</pre>
<h4 name="Line_by_line">Line by line</h4>
<pre>// 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);
</pre>
<h4 name="Asynchronously">Asynchronously</h4>
<p>This will allow you to read a file without locking up the UI thread.</p>
<pre>// |file| is nsIFile
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var fileURI = ios.newFileURI(file);
var channel = ios.newChannelFromURI(fileURI);
var observer = {
  onStreamComplete : function(aLoader, aContext, aStatus, aLength, aResult)
  {
    alert(aResult);
  }
};
var sl = Components.classes["@mozilla.org/network/stream-loader;1"]
                   .createInstance(Components.interfaces.nsIStreamLoader);
sl.init(channel, observer, null);
</pre>
<h4 name="Binary_File">Binary File</h4>
<p>For instance, to get the data in a PNG file:</p>
<pre>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());
</pre>
<h3 name="Writing_to_a_file">Writing to a file</h3>
<div class="note">
<p><strong>NOTE</strong>: This code is not intl-aware. Writing non-ASCII characters <strong>will not work correctly</strong>. See <a href="/en/Writing_textual_data" title="en/Writing_textual_data">Writing textual data</a> for intl-aware code.</p>
</div>
<pre>// 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.
foStream.write(data, data.length);
foStream.close();
</pre>
<div class="note">
<p><strong>NOTE</strong>: The file status flags used in the <code>nsIFileOutputStream::init()</code> function are documented in <a href="/en/PR_Open#Parameters" title="en/PR_Open#Parameters">PR_Open</a>. For more information refer directly to {{ Source("nsprpub/pr/include/prio.h") }}</p>
</div>
<h4 name="Writing_a_Binary_File">Writing a Binary File</h4>
<p>For example, here we can write PNG data to a file.</p>
<pre>// 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, 600);
            
var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"]
                       .createInstance(Components.interfaces.nsIFileOutputStream);
stream.init(aFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate
            
stream.write(pngBinary, pngBinary.length);
if (stream instanceof Components.interfaces.nsISafeOutputStream) {
    stream.finish();
} else {
    stream.close();
}
</pre>
<h4 name="Copy_a_stream_to_a_file">Copy a stream to a file</h4>
<p>This function returns a basic stream listener that copies all of the data from an input stream to a file. Takes an nsIFile as an argument, which is assumed to be open and created; depending on what you're doing, you might prefer to create the file in onStartRequest and close it in onStopRequest.</p>
<pre>function StreamToFile(file)
{
    var output = Components.classes["@mozilla.org/network/file-output-stream;1"]
                           .createInstance(Components.interfaces.nsIFileOutputStream);
    var buffer = Components.classes["@mozilla.org/network/buffered-output-stream;1"]
                           .createInstance(Components.interfaces.nsIBufferedOutputStream);
    output.init(file, 0x02 | 0x08 | 0x20, 0664, null);
    buffer.init(output, 8192);

    return {
        onStartRequest: function(request, context) { },

        onDataAvailable: function onDataAvailable(request, context, stream, offset, count)
        {
            while(count &gt; 0)
                count -= buffer.writeFrom(stream, count);
        },

        onStopRequest: function(request, context) { }
    };
}
</pre>
<h3 name="More">More</h3>
<p>There are more methods and properties on <code>nsIFile</code> and <code>nsILocalFile</code> interfaces, please refer to documentation on <a class="external" href="http://xulplanet.com/references/xpcomref/group_Files.html">XUL Planet</a>. Those methods/properties are mostly self-explanatory, so we haven't included examples of using them here.</p>
<p>{{ languages( { "fr": "fr/Extraits_de_code/Fichiers_E//S", "ja": "ja/Code_snippets/File_I//O", "pl": "pl/Fragmenty_kodu/Plik_I//O" } ) }}</p>
Revert to this revision