|
|
(38 intermediate revisions by 10 users not shown) |
Line 1: |
Line 1: |
| {{extdev}}
| | Moved [https://developer.mozilla.org/en/Code_snippets:File_I/O] (MDC). |
| | | [[Category:Redirects]] |
| This article describes local file input/output in Javascript.
| |
| | |
| You access the filesystem using Mozilla [http://xulplanet.com/tutorials/xultu/xpcom.html XPCOM] components. The list of components used for local IO is available at [http://xulplanet.com/references/xpcomref/group_FilesandStreams.html XulPlanet.com].
| |
| | |
| ==Available libraries==
| |
| There are a few JavaScript wrappers for IO XPCOM components. See [http://jslib.mozdev.org/ JSLib] and MonkeeSage's [http://gratisdei.com/io.js IO module].
| |
| MonkeeSage's module is much smaller and very easy to use (simple examples are included in the module).
| |
| | |
| ==Creating a file object ("opening" files)==
| |
| <pre>var file = Components.classes["@mozilla.org/file/local;1"].
| |
| createInstance(Components.interfaces.nsILocalFile);
| |
| file.initWithPath("/home");</pre>
| |
| | |
| Note: the path passed to ''initWithPath()'' should be in 'native' form (eg. <tt>"C:\\Windows"</tt>). If you need to use ''file://'' URIs as initializers, see below.
| |
| | |
| Also note, that ''initWithPath()'' / ''initWithFile()'' functions don't throw an exception if specified file does not exist. An exception is thrown when methods that require the file existance are called, e.g. ''isDirectory()'', ''moveTo()'' etc.
| |
| | |
| ==Getting special files==
| |
| <pre>// get profile directory
| |
| var file = Components.classes["@mozilla.org/file/directory_service;1"].
| |
| getService(Components.interfaces.nsIProperties).
| |
| get("ProfD", Components.interfaces.nsIFile);</pre>
| |
| | |
| Here are some strings you can put in place of "ProfD" (stolen from MonkeeSage's IO module comments)
| |
| | |
| {| border="1" cellpadding="5" rules="all"
| |
| ! 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)
| |
| |}
| |
| | |
| Look in the Source for other strings available: [http://lxr.mozilla.org/seamonkey/source/xpcom/io/nsDirectoryServiceDefs.h] [http://lxr.mozilla.org/seamonkey/source/xpcom/io/nsAppDirectoryServiceDefs.h].
| |
| | |
| ==Getting an nsILocalFile from user using nsIFilePicker==
| |
| See [[Dev : nsIFilePicker]].
| |
| | |
| ==nsIFile and path strings==
| |
| You can use nsIFile::path to get platform-specific path string, eg. <tt>C:\Windows\System32</tt> or <tt>/usr/share</tt>. If you want to get a ''file://'' URL of a file or an nsIFile from ''file://'' URL, you need to use [http://xulplanet.com/references/xpcomref/ifaces/nsIFileProtocolHandler.html nsIFileProtocolHandler]:
| |
| <pre>// file is nsIFile
| |
| var ios = Components.classes["@mozilla.org/network/io-service;1"].
| |
| getService(Components.interfaces.nsIIOService);
| |
| var fileHandler = ios.getProtocolHandler("file").
| |
| QueryInterface(Components.interfaces.nsIFileProtocolHandler);
| |
| var URL = fileHandler.getURLSpecFromFile(file);</pre>
| |
| | |
| To load from ''file://'', ''http://'', ''chrome://'', ''resource://'' and other URLs directly, use [http://xulplanet.com/references/xpcomref/ifaces/nsIChannel.html nsIChannel]. Until a knowledge base article on [[nsIChannel]] is written, [http://forums.mozillazine.org/viewtopic.php?p=921150#921150 here]'s an example for you.
| |
| | |
| Note: do '''not''' use nsILocalFile::persistentDescriptor to get the file path!
| |
| | |
| 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 ([[Dev : Using preferences|more about preferences in Mozilla]]):
| |
| | |
| ===Absolute path (nsILocalFile)===
| |
| To store arbitrary path in user preferences, use this code.
| |
| <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>
| |
| | |
| ===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:
| |
| <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>
| |
| | |
| ==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 this code: <tt>file.append("myfile.txt");</tt> - to make ''file'' point to myfile.txt inside that directory.
| |
| | |
| Notes: avoid using <tt>dir.path+"\\"+"myfile.txt"</tt>, as it is not cross-platform code.
| |
| Using something like
| |
| <tt>((path.search(/\\/) != -1) ? path + "\\" : path + "/") + "myfile.txt";</tt>
| |
| is possible, but the 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 <tt>|nsIFile|</tt>s corresponding to sub-files/subdirectories of given directory. You can tell files from folders by calling <tt>nsIFile::isDirectory()</tt> and <tt>nsIFile::isFile()</tt> methods on each <tt>|entry|</tt>.
| |
| | |
| <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>
| |
| | |
| ==Reading from a file==
| |
| | |
| ===Simple===
| |
| <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, false);
| |
| sstream.init(fstream);
| |
| var bytes = sstream.available();
| |
| data += sstream.read(bytes);
| |
| sstream.close();
| |
| fstream.close();
| |
| alert(data);</pre>
| |
| | |
| ===Line by line===
| |
| <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>
| |
| | |
| ===Asynchronously===
| |
| | |
| This will allow you to read a file without locking up the UI thread.
| |
| | |
| <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>
| |
| | |
| ==Writing to a file==
| |
| <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.
| |
| stream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
| |
| stream.write(data, data.length);
| |
| stream.close();</pre>
| |
| | |
| Flags parameter to the <tt>nsIFileOutputStream::init()</tt> function
| |
| (For more information refer to [http://lxr.mozilla.org/seamonkey/source/nsprpub/pr/include/prio.h prio.h file]).
| |
| | |
| '''flags''': The file status flags. It is a bitwise OR of the following bit flags (only one of the first three flags below may be used):
| |
| {| border="1" cellpadding="5" rules="all"
| |
| ! Name !! Value !! Description
| |
| |-
| |
| | PR_RDONLY || 0x01 ||| Open for reading only.
| |
| |-
| |
| | PR_WRONLY || 0x02 ||| Open for writing only.
| |
| |-
| |
| | PR_RDWR || 0x04 ||| Open for reading and writing.
| |
| |-
| |
| | PR_CREATE_FILE || 0x08 |||
| |
| If the file does not exist, the file is created.
| |
| If the file exists, this flag has no effect.
| |
| |-
| |
| | PR_APPEND || 0x10 |||
| |
| The file pointer is set to the end of the file prior to each write.
| |
| |-
| |
| | PR_TRUNCATE || 0x20 |||
| |
| If the file exists, its length is truncated to 0.
| |
| |-
| |
| | PR_SYNC || 0x40 |||
| |
| If set, each write will wait for both the file data and file status to be physically updated.
| |
| |-
| |
| | PR_EXCL || 0x80 |||
| |
| With PR_CREATE_FILE, if the file does not exist, the file is created.
| |
| If the file already exists, no action and NULL is returned.
| |
| |}
| |
| | |
| [[Category:Development|File IO]] [[Category:Example code|File IO]]
| |