在nodejs中,檔案系統模組提供檔案操作api。檔案系統模組(簡稱fs模組)允許使用者存取電腦上的檔案系統並與之互動;使用fs模組可以實現檔案及目錄的創建,寫入、刪除等操作。
本教學操作環境:windows7系統、nodejs 12.19.0版,DELL G3電腦。
注意:讀取檔案和寫入檔案可能理解很枯燥,但是我每次學習這樣的文章的時候都是為了下一篇文章做好準備的,因為我下一篇文章的demo需要使用到該方面的知識,所以我會把需要的理解的知識統統記錄一遍的。
在Node.js中,使用fs模組來實作所有檔案及目錄的創建,寫入及刪除操作。
1、讀文件的方法:
在執行讀取文件操作時,可以使用readFile方法與readFileSync方法讀取文件,有Sync等字樣的是同步方法,沒有這個字樣的是非同步方法讀取,同步方法和非同步方法的差別是:同步方法立即傳回操作的結果,先看下相關的API:
1) readFileSync同步讀取檔案API
使用方法讀取如下:
fs.readFileSync(filename, [options]);
filename參數:用於指定讀取檔案的完整檔案路徑及檔案名稱。
options參數:該值為一個對象,它可以指定讀取檔案時使用flag屬性指定該檔案採取什麼操作,預設為'r'; 可以指定值有如下:
'r': 讀取文件,如果文件不存在會拋出異常。
'r ': 讀取並寫入文件,如果文件不存在會拋出例外。
'rs': 同步方式讀取檔案並且通知作業系統忽略本機檔案系統的快取,如果檔案不存在會拋出例外。
'w': 寫入文件,如果文件不存在則建立該文件,如果文件已存在則清空文件內容。
'w ': 讀取並寫入文件,其他功能和 'w'一樣。
'a': 追加寫入文件,如果文件不存在則建立該文件。
'a ': 讀取並追加寫入文件,文件不存在就建立文件。
在options參數中,我們可以使用encoding屬性指定使用何種編碼格式來讀取該文件,屬性值有'utf-8', 'ascii', 'base64' , 下面先看看簡單的demo。如下所示:
先看下目錄結構如下:
### 目录结构如下: demo1 # 工程名 | |--- readFile # 读取文件的文件夹 | | |-- index.html # html文件 | | |-- index.js # js文件 | | |-- package.json | | |-- node_modules
如下程式碼讀取檔碼:
const fs = require('fs'); try { const data = fs.readFileSync('./index.html', 'utf-8'); // 等待操作结果返回,然后打印结果 console.log(data); } catch(e) { console.log('读取文件发生错误'); }
在命令列中執行node index.js 然後列印結果如下:
2) 非同步讀取檔案的API使用方法如下:
fs.readFile(filename, [options], callback);
filename 和options 和同步方法的參數是一樣的。
callback參數 是用於檔案讀取完後執行的回呼函數。如下程式碼所示:
const fs = require('fs'); fs.readFile('./index.html', 'utf-8', (err, data) => { if (err) { console.log('读取文件时发生错误'); } else { console.log(data); } });
執行的結果和上面是一樣的。這裡就不截圖了。
寫入文件,我們使用fs模組中的 writeFile 方法 或 wirteFileSync方法。 writeFile使用方法如下(wirteFileSync方法類似,無非沒有callback參數):
fs.writeFile(filename, data, [options], callback);
filename參數 為指定需要被寫入檔案的完整路徑及檔案名稱。
data參數 為指定需要寫入的內容,值可以是一個字串或一個Buffer對象,該字串或緩衝區中的內容將被完整地寫入到文件中。
options值為物件(可選),選項名稱為flag,它有以下選項值:
'flag': 用來指定該檔案採取何種操作,預設值為'w', 意義是寫入檔案。該指定項所有值和上面readFile的值是一樣的。
(文件不存在就會建立該文件,文件存在時重寫該文件)。
'mode': 此屬性用於指定當檔案被開啟時對該檔案的讀寫權限。預設值為 0666(可讀寫)。還有很多值自己可以百度了解下。
'encoding': 用於指定使用何種編碼格式來寫入該檔案。可指定屬性值為 'utf8'、'ascii'、'base64'。
callback: 此參數用於檔案讀取完畢時執行的回呼函數。
下面我們簡單的做一個demo,在我們目錄下的 index.js 檔案中寫程式碼,在該目錄下建立一個 message.txt檔案並寫入兩行文字。如下程式碼:
const fs = require('fs'); const str = '这是第一行。\r\n这是第二行'; fs.writeFile('./message.txt', str, (err) => { if (err) { console.log('写入文件操作失败'); } else { console.log('写入文件操作成功'); } });
如下圖執行指令:
#在目錄下會產生 message.txt文件,如下圖
然后我们打开文件,会看到其写入的内容。
2)写入buffer对象,如下代码:
const fs = require('fs'); const str = new Buffer('我喜爱编程'); fs.writeFile('./message.txt', str, (err) => { if (err) { console.log('写入文件操作失败'); } else { console.log('写入文件操作成功'); } });
在message.txt中可以看到 '我喜爱编程' 几个字。
3)设置options参数flag属性选项,比如追加数据这些,如下代码:
const fs = require('fs'); const options = { flag: 'a'}; fs.writeFile('./message.txt', '这是追加的数据', options, (err) => { if (err) { console.log('写入文件操作失败'); } else { console.log('写入文件操作成功'); } });
message.txt内容编程如下了:我喜爱编程这是追加的数据
4)复制图片文件
我们可以通过readFile方法读取应用程序对应目录下的一个图片文件,在读取文件时使用base64编码,在该回调函数中使用writeFile方法,在该方法中使用base64编码将读取到的图片文件数据复制到另一个图片文件中。如下代码:
const fs = require('fs'); fs.readFile('./images/1.png', 'base64', (err, data) => { fs.writeFile('./images/xx.png', data.toString(), 'base64', (err) => { if (err) { console.log('写文件操作失败'); } else { console.log('写文件操作成功'); } }); });
在image下有一个 1.png, 它会先复制,然后写入 xx.png中(该文件之前不存在的,会创建该图片文件)。
3.1)打开文件open方法或openSync方法
要实现在文件中的指定位置处读入内容,首先我们需要打开该文件,fs模块中的open方法或openSync方法打开文件。open方法使用方式如下所示:
fs.open(filename, flags, [mode], callback);
前三个参数和readFile的参数是一个意思的。最后一个参数是执行完成后的回调函数。该回调函数有两个参数,第一个是打开文件失败时的错误对象,第二个参数为一个整数值,代表打开文件时返回的文件描述符。
下面我们来打开我们刚刚创建的 message.txt文件,如下代码:
const fs = require('fs'); fs.open('./message.txt', 'r', (err, fd) => { console.log(fd); });
执行结果如下所示:
3.2)从指定的位置读取文件
如上面打开文件之后,我们可以在其回调函数使用fs模块中的read方法或readSync方法从文件的指定位置处读取文件,也可以使用fs模块中的write方法或writeSync方法从文件中指定处写入数据。
fs.read(fd, buffer, offset, length, position, callback);
fd参数是 上面open打开文件返回的文件描述符。
buffer参数 是一个buffer对象,用于指定将文件数据读取到那个缓存区中。
offset:用于指定向缓冲区中写入数据的开始位置。
length:用于指定从文件中读取的字节数。
position: 用于指定读取文件时的开始位置。
callback:用于指定文件操作完毕时的回调函数。如下所示:
function(err, bytesRead, buffer) {}
err: 为操作失败时的错误对象。
bytesRead: 代表实际读取的字节数。
buffer:为被读取的缓冲区对象。
下面我们来看个demo代码如下:
const fs = require('fs'); // message.txt 内容为:我喜爱编程这是追加的数据 fs.open('./message.txt', 'r', (err, fd) => { const buf = new Buffer(255); // 一个汉字的utf编码为三个字节数据 fs.read(fd, buf, 0, 9, 3, (err, bytesRead, buffer) => { console.log(buffer.slice(0, bytesRead).toString()); // 喜爱编 }); });
如上代码message.txt内容为:我喜爱编程这是追加的数据,position为3,从第三个字节开始读取文件,然后长度为9个字节,一个汉字3个字节,因此结果为 '喜爱编';
在文件被打开后,可以使用fs模块中的write方法或writeSync方法从一个缓存区中读取数据并从文件的指定位置处写入这些数据。使用方法如下所示:
fs.write(fd, buffer, offset, length, position, callback);
fd参数为描述符。
buffer参数为一个Buffer对象,用于指定从哪个缓存区中读取数据。
offset参数用于指定从缓存区中读取数据时的开始读取位置。
length参数用于指定从缓存区中读取的字节数。
position参数值用于指定写入文件时的开始位置。
callback参数用于指定文件写入操作执行完毕时的回调函数。该回调函数如下:
function(err, written, buffer) {}
err参数为写入失败时的错误对象。
written: 代表被写入的字节数。
buffer: 代表被读取的缓冲区对象。
下面是一个简单的demo,如下所示:
const fs = require('fs'); const buf = new Buffer('我喜爱编程'); fs.open('./message.txt', 'w', (err, fd) => { fs.write(fd, buf, 3, 9, 0, (err, written, buffer) => { if (err) { console.log('写文件操作失败'); } else { console.log('写文件操作成功'); } }); });
在message.txt中显示为 喜爱编 这三个字。
5.1) 创建目录mkdir和mkdirSync方法
在fs模块中,可以使用mkdir方法创建目录,该方法使用方式如下所示:
fs.mkdir(path, [mode], callback);
path参数用于指定需要被创建的目录完整路径及目录名。
mode参数用于指定该目录的权限,默认值为0777(表示任何人可读写该目录)。
callback是回调函数。
下面是一个简单的demo,如下所示:
const fs = require('fs'); fs.mkdir('./test', (err) => { if (err) { console.log('创建目录操作失败'); } else { console.log('创建目录操作成功'); } });
如下所示:
5.2)读取目录readdir和readdirSync方法
在fs模块中,使用readdir方法读取目录,该方法使用如下所示
fs.readdir(path, callback);
path参数用于指定需要被读取的目录的完整路径及目录名。
callback参数用于指定读取目录操作的回调函数。该回调函数如下所示:
function(err, file) {}
err 为读取目录操作失败的回调函数。
file参数值为一个数组,读取到的文件中的所有文件名。
如下demo所示:
const fs = require('fs'); fs.readdir('./', (err, files) => { if (err) { console.log('读取目录操作失败'); } else { console.log(files); } });
如下图所示:
6.1)查看文件或目录的信息
在fs模块中,可以使用stat方法或lstat方法查看一个文件或目录的信息。这两个方法唯一的区别是当查看符号链接文件的信息
时,必须使用lstat方法。使用方法如下所示:
fs.stat(path, callback); fs.lstat(path, callback);
path参数用于被查看的文件或目录的完整路径及文件名或目录名。
callback是回调函数。如下回调函数
function(err, stats) {}
err 参数值为查看文件或目录信息操作失败时触发的错误对象。
stats参数值为一个 fs.Stats对象,该对象有如下一些方法,在这些方法中不包含任何参数。
isFile: 用于判断被查看的对象是否为一个文件,如果是则返回true,否则的话返回false。
isDirectory: 用于判断被查看的对象是否为一个目录,如果是的话返回true,否则的话返回false。
还有很多很多其他的方法,这里不一一介绍,用的比较少,有需要的话,可以自己百度一下看看。
下面是使用 stat的使用demo,查看应用程序根目录下的 message.txt文件并且在回调函数中的第二个参数值 fs.Stats对象在控制台中的输出有哪些?
const fs = require('fs'); fs.stat('./message.txt', (err, stats) => { console.log(stats); });
如下图所示显示:
6.2)检查文件或目录是否存在exists和existsSync方法
在fs模块中,可以使用exists方法检查一个文件或目录是否存在,该方法使用方式如下所示:
fs.exists(path, callback);
path参数:用于指定需要被检查的文件或目录的完整路径。
callback: 是回调函数,该回调函数如下所示:
function(exists) {}
exists参数,当文件或目录存在时,该参数值为true,否则的话,该参数值为false。
下面是一个简单的demo,如下代码所示:
const fs = require('fs'); // 该目录是存在的 fs.exists('./message.txt', (exists) => { console.log(exists); // true }); // 该目录是不存在的 fs.exists('./message2.txt', (exists) => { console.log(exists); // false });
6.3) 获取文件或目录的绝对路径realpath和realpathSync方法
在fs模块中,可以使用 realpath方法获取一个文件或目录的绝对路径,该方法使用如下所示:
fs.realpath(path, [cache], callback);
cache 参数是可选的,path和callback是必须的。
path参数为需要查看的文件或目录的完整路径。
cache参数为一个对象,其中存放了一些预先指定的路径。具体的百度下,这个参数用的不多。
callback是回调函数,该回调函数有2个参数,err参数值为获取目录的绝对路径失败的错误对象。resolvedPath参数值为获取
到的文件或目录的绝对路径。
下面是一个简单的demo,如下所示:
const fs = require('fs'); fs.realpath('./message.txt', (err, resolvedPath) => { if (err) { throw err; } else { console.log(resolvedPath); } });
执行如下所示:
6.4) 使用ReadStream对象读取文件
在fs模块中,可以使用createReadStream方法创建一个将文件内容读取为流数据的ReadStream对象,该方法使用如下所示:
fs.createReadStream(path, [options]);
path 该参数用于指定需要被读取的文件的完整路径及文件名。
options为一个对象,它有如下属性:
flags: 用于指定对该文件采取什么操作,默认值为 'r', 它的用法和readFile方法中的flags属性一样的。
encoding: 指定使用什么编码来读取该文件,可指定的值有 'utf8', 'ascii', 'base64'. 默认值为null.
start: 指定文件的开始读取位置。
end: 指定文件的结束读取位置。
还有很多其他的参数,这里不一一讲解,可以自行百度下即可。
下面简单的使用一个demo来了解下使用:如下代码:
const fs = require('fs');/* 一个汉字三个字节,message.txt的内容为:我喜爱编写代码 因此从第三个位置开始,到第十二个位置结束,因此数据应该为 喜爱编写*/const options = { start: 3, end: 12}; const file = fs.createReadStream('./message.txt', options); file.on('open', (fd) => { console.log('开始读取文件'); }); file.on('data', (data) => { console.log('读取到的数据:' + data); }); file.on('end', () => { console.log('文件已全部读取完毕'); }); file.on('close', () => { console.log('文件被关闭'); }); file.on('error', (err) => { console.log('读取文件失败'); });
如下图所示:
我们可以使用 ReadStream对象的pause方法暂停data事件的触发,同时也意味着停止文件的读取操作。而已经被读取到的操作系统缓存区中的数据也将被暂时保存在操作系统缓冲区中,在使用了pause方法暂停data事件的触发之后,也可以使用ReadStream对象的resume方法恢复data事件的触发,也就意味着可以继续读取文件的数据。
如下demo:
const fs = require('fs'); const readStream = fs.createReadStream('./message.txt'); readStream.pause(); readStream.on('data', (data) => { console.log('获取到的数据为:' +data); }); setTimeout(() => { readStream.resume(); }, 1000);
读取过程中,断听了一秒后,继续把数据读出来了。
注意:写入文件的方法是 WriteStream, 使用方式和读方式类似,这里不多介绍。
【推荐学习:《nodejs 教程》】
以上是nodejs中哪個模組提供檔案操作api的詳細內容。更多資訊請關注PHP中文網其他相關文章!