陈建华的博客
专注web开发
Firefox 扩展开发(七):文件I/O
2014-09-26 15:36:46   阅读2097次

本文编译自https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO

存取文件需要xpcom组件 nsIFile 或其扩展 nsILocalFile

创建 nsIFile对象(“打开”文件)

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

NOTE: 传递给initWithPath()的路径应该是“原生”格式 (e.g. "C:\\Windows"). 如果要用file:// URIs来初始化,见 nsIIOService .

NOTE: 如果文件不存在,initWithPath() / initWithFile()不抛任何异常. 需要文件存在的方法被执行时会抛出异常, e.g. isDirectory(), moveTo(), etc.

得到特别的文件

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

// NOTE: "file" nsIFile的实例对象. 如果要得到文件系统路径,用file.path
可以放在 "ProfD" 位置的字符串:

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)

其它可用的字符串去查源代码: xpcom/io/nsAppDirectoryServiceDefs.h , xpcom/io/nsDirectoryServiceDefs.h .

得到扩展文件夹Via nsIExtensionManager

//install.rdf中扩展的ID
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
//返回扩展install.rdf的nsIFile对象
var file = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "install.rdf");
var filestring = file.path;

枚举Windows分区

var root = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
root.initWithPath("\\\\.");
var drivesEnum = root.directoryEntries, drives = [];
while (drivesEnum.hasMoreElements()) {
drives.push(drivesEnum.getNext().
QueryInterface(Components.interfaces.nsILocalFile).path);
}

创建文件夹

创建一个文件夹,用 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);
}
在Profile文件夹创建目录"DIR". 更多信息参见 nsIFile.create reference.

创建临时文件

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

用户由nsIFilePicker输入

The file picker component (nsIFilePicker) 可以用来打开标准的打开/保存对话框. 返回用户指定的文件 nsIFile.

nsIFile和路径字符串

你能用nsIFile.path得到特定平台的路径字符串, e.g. "C:\Windows\System32" or "/usr/share".

得到一个文件的URL,用 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是nsIURI;得到字符串, "file://...", 用URL.spec

从 'file://' URL得到nsIFile,用 nsIFileURL:

var file = URL.QueryInterface(Components.interfaces.nsIFileURL).file;
// file is now a nsIFile

file://http://chrome://resource:// 和其它 URLs直接载入, 用 XMLHttpRequest 或 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.

存储nsILocalFile到preferences

下面2个片段展示了存储文件路径到用户preferences的正确方式 (more about preferences in Mozilla):

绝对路径 (nsILocalFile)

// |file| is nsILocalFile
// 1. 写路径到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. 从 prefs读路径
var file = prefs.getComplexValue("filename", Components.interfaces.nsILocalFile);

相对路径 (nsIRelativeFilePref)

储存对上表中列出的文件夹的相对路径,例如到profile的相对路径,用下面的代码。

// 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.

用nsIFile浏览从指定的目录得到文件

假定文件是到某些目录(e.g.: a user profile directory)的nsIFile点 , 你能用file.append("myfile.txt")制作那个目录的 myfile.txt文件点。

在指定的目录枚举文件

下面的片段制作给定目录的“子文件”/子目录nsIFiles数组。你可以用nsIFile.isDirectory() and nsIFile.isFile()来分辨文件和文件夹。

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

读一个文件简单

// |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 = {}) {
cstream.readString(-1, str); // read the whole file and put it in str.value
data = str.value;
}
cstream.close(); // this closes fstream

alert(data);

逐行

NOTE: 下面的简单代码不操纵非ASCII字符。 如何读其它的字符编码见Reading textual data 。

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

异步

这允许读文件时不死锁UI线程。

Note: The nsIStreamLoader interface was changed in Bug 233780 so that the init() method now only takes a single observer parameter. The below code attempts to use the correct calls based on the version of Gecko being run.

var appInfo=Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var isOnBranch = appInfo.platformVersion.indexOf("1.8") == 0;
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);
if (isOnBranch) {
sl.init(channel, observer, null);
} else {
sl.init(observer);
channel.asyncOpen(sl, channel);
}

二进制文件

得到一个PNG文件的数据:

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

写文件

// 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.

// 如果你确信数据中永远不会有非ASCII数据,你也可以直接执行foStream.writeData
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: nsIFileOutputStream::init()函数中的状态标志文档在 PR_Open. 更多信息参见 nsprpub/pr/include/prio.h

写二进制文件

写PNG数据到一个文件

// pngBinary 已经存在
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();
}




-----------------------------------------------------
转载请注明来源此处
原地址:#

-----网友评论----
暂无评论
-----发表评论----
微网聚博客乐园 ©2014 blog.mn886.net 鲁ICP备14012923号   网站导航