NodeJS文件文件夹/文件操作

判断是文件还是文件夹

同步

1
2
3
4
5
6
7
8
9
10
const fs = require('fs');

var pathName = "E:\image"

var stat = fs.lstatSync(pathName);

console.log(JSON.stringify(stat))

console.log('是否是文件:'+stat.isFile()) //是文件吗
console.log('是否是文件夹:'+stat.isDirectory()) //是文件夹吗

异步

1
2
3
4
5
6
7
8
const fs = require('fs');

var pathName = "E:\image"

fs.stat(pathName, function(err, data){
console.log('是否是文件:'+data.isFile()) //是文件吗
console.log('是否是文件夹:'+data.isDirectory()) //是文件夹吗
});

创建文件夹

同步

1
2
3
4
5
6
7
const fs = window.require('fs'); // 引入文件系统模块
const {app} = window.require("electron").remote;

let mypath = app.getPath("documents") + "/space/";
if(!fs.existsSync(mypath)) {
fs.mkdirSync(mypath);
}

异步

1
2
3
4
5
6
const fs = window.require('fs'); // 引入文件系统模块

fs.mkdir(mypath, (err) => {
if(err) throw err; // 如果出现错误就抛出错误信息
console.log('文件夹创建成功');
})

创建多层目录

1
2
3
4
5
6
7
const path = require("path");
const fs = require("fs");

let mypath = path.join(__dirname,"a","b","c","d");
fs.mkdir(mypath, { recursive: true }, (err) => {
if (err) throw err;
});

同步

1
2
3
4
5
6
7
const path = require("path");
const fs = require("fs");

let mypath = path.join(__dirname,"a","b","c","d");
if (!fs.existsSync(mypath)) {
fs.mkdirSync(mypath, { recursive: true });
}

获取文件所在文件夹

推荐方式

1
2
3
4
5
6
7
8
const path = window.require("path");
const {app} = window.require("electron").remote;

let exepath = app.getPath("exe");

path.dirname(exepath);
// 或者
path.resolve(exepath, '..');

Electron渲染进程中的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const path = window.require("path");
const {app} = window.require("electron").remote;

get_exe_folder() {
let exepath = app.getPath("exe");
return path.dirname(exepath);
}

let exe_folder = this.get_exe_folder();

// 拼接文件路径
const filepath = path.join(
exe_folder,
"_temp",
filename
);

// 创建所有父级文件夹
let parent_folder = path.dirname(filepath)
try {
if (!fs.existsSync(parent_folder)) {
fs.mkdirSync(parent_folder, {recursive: true});
}
} catch (e) {
}

// 如果文件存在删除文件
if (fs.existsSync(filepath)) {
fs.unlinkSync(filepath);
}

注意

Electron渲染进程中获取path,一定要添加window.;

1
const path = window.require("path");

千万不要用以下两种

1
2
3
import path from "path";
// 或者
const path = require("path");

这两中方式引用的并不是NodeJS的path,在Windows下这样获取的path.sep/,而不是\,导致以下的方法都会出现问题。

下面就是引用path错误导致的两种问题:

错误示例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const path = require("path");

let exepath = app.getPath("exe");
console.info("exepath", exepath);
let path_arr = exepath.split("\\");
console.info("path.sep", path.sep);
path_arr.pop();
let mypath = path_arr.join("\\");
console.info("mypath", mypath);
console.info("path.resolve(exepath, '..')", path.resolve(exepath, '..'));
console.info("path.dirname(exepath)", path.dirname(exepath));

const filepath = path.join(
exepath,
"_temp",
"1.jpg"
);
console.info("filepath", filepath);

结果

exepath D:\Project\Electron\school_live_client\node_modules\electron\dist\electron.exe
path.sep /
mypath D:\Project\Electron\school_live_client\node_modules\electron\dist
path.resolve(exepath, ‘..’) /
path.dirname(exepath) .
filepath D:\Project\Electron\school_live_client\node_modules\electron\dist\electron.exe/_temp/1.jpg

错误示例2

dirname方法获取的是正确的,而resolve获取的路径最前面会多一个/

1
2
3
4
5
6
7
8
9
10
11
12
const path = require("path");

let exe_folder = this.get_exe_folder();
const filepath = path.join(
exe_folder,
"_temp",
filename
);

let mypath = path.dirname(filepath)
console.info("mypath", mypath);
console.info("mypath2", path.resolve(filepath, '..'));

结果

mypath D:/Project/Electron/school_live_client/node_modules/electron/dist/_temp
mypath2 /D:/Project/Electron/school_live_client/node_modules/electron/dist/_temp

判断文件和文件夹是否存在

同步

1
2
3
if(!fs.existsSync(mypath)) {
fs.mkdirSync(mypath);
}

异步

1
2
3
fs.exists("dirName", function(exists) {
console.log(exists ? "创建成功" : "创建失败");
});

删除文件夹及文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var fs = require('fs'); // 引入fs模块
function deleteall(path) {
  var files = [];
  if(fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach(function(file, index) {
      var curPath = path + "/" + file;
      if(fs.statSync(curPath).isDirectory()) { // recurse
        deleteall(curPath);
      } else { // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
};

文件读取写入

创建文件

1
2
3
4
5
6
7
8
9
10
11
12
fs.access(filename, fs.constants.F_OK, (err) => {
if (!err) {
fs.unlinkSync(filename);
}
fs.writeFile(filename, '', {
'flag': 'a'
}, function (err) {
if (err) {
throw err;
}
});
});

读取文件内容

同步读取

1
2
3
var fs=require("fs"); 
let mcontent=fs.readFileSync(filepath,"utf-8");
console.log(mcontent);

异步读取

1
2
3
4
5
6
7
8
var fs=require("fs"); 
fs.readFile(filepath,'utf-8',function(err,data){
if(err){
console.log("error");
}else{
console.log(data);
}
});

写入文件内容

同步写入

1
fs.writeFileSync(filename,data,[options])

示例

1
2
3
4
5
6
7
8
9
const fs = require('fs')

const content = '123456'

try {
const data = fs.writeFileSync('/Users/me/test.txt', content)
} catch (err) {
console.error(err)
}

默认情况下,此API将替换文件的内容(如果已经存在)。

您可以通过指定标志来修改默认值:

1
fs.writeFile('/Users/me/test.txt', content, { flag: 'a+' }, (err) => {})

您可能会使用的标志是

  • r+ 打开文件进行读写
  • w+ 打开文件进行读写,将流放在文件的开头。 如果不存在则创建文件
    打开一个文件进行写入,将流放在文件末尾。 如果不存在则创建文件
  • a+ 打开文件进行读写,将流放在文件末尾。 如果不存在则创建文件

您可以在https://nodejs.org/api/fs.html#fs_file_system_flags中找到更多标志

异步写入

1
fs.writeFile(filename,data,[options],callback);

参数说明

  • filename:文件名

  • data:需要写入的数据

  • option:options参数值为一个对象,参数如下

    • flag属性:用于指定对该文件采取何种操作,默认值为’w’(文件不存在时创建该文件,文件已存在时重写该文件),可指定值及其含义与readFile方法中使用的options参数值中的flag属性的可指定值及其含义相同。

    • mode属性:用于指定当文件被打开时对该文件的读写权限,默认值为0666(可读写)。该属性值及fs模块中的各方法中的mode参数值的指定方法均如下所示:使用4个数字组成mode属性值或?mode参数值,其中第一个数字必须是0,第二个 数字用于规定文件或目录所有者的权限,第三个数字用于规定文件或目录所有者所属用户组的权限,第四个数字规定其他人的权限。可以设定的数字如下所示:

      • 1:执行权限
      • 2:写权限
      • 4:读权限
    • encoding属性:用于指定使用何种编码格式来写入该文件。可指定属性值为“utf8”、“ascii”与“base64”。

      当data参数值为一个Buffer对象时该属性值被忽略,使用默认编码格式utf8来执行文件的写入。

  • callback:回调函数

同步追加内容到文件底部

1
fs.appendFileSync(filename,data,[options])

异步追加内容到文件底部

1
fs.appendFile(filename,data,[options],callback)

文件流写入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const fs = require('fs')

const writer = fs.createWriteStream('./a.txt', {
flags: 'a', //如果要把内容追加到文件原有的内容的后面,则设置flags为'a',此时设置start无效
})

//写入数据到流
writer.write(',适合去郊游,', 'utf8')
//再次向文件写入数据,会从当前位置开始写入
writer.write('咱们出发把!', 'utf8')

//关闭写入流,表明已没有数据要被写入可写流
writer.end()

writer.on('open', () => {
console.log('文件已被打开', writer.pending)
})
writer.on('ready', () => {
console.log('文件已为写入准备好', writer.pending)
})
writer.on('close', () => {
console.log('文件已被关闭')
console.log("总共写入了%d个字节", writer.bytesWritten)
console.log('写入的文件路径是'+ writer.path)
})

获取文件夹下文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const path = require("path");
const fs = require("fs");

let filepath_arr = [];

function mapDir(dir, containSonDir) {
let files = fs.readdirSync(dir);
files.forEach((filename) => {
let pathname = path.join(dir, filename);
let stats = fs.statSync(pathname);
if (stats.isDirectory()) {
if (containSonDir) {
mapDir(pathname);
}
} else if (stats.isFile()) {
let index = filename.lastIndexOf(".");
//获取后缀
let ext = filename.substr(index + 1);
if (ext === "conf") {
filepath_arr.push(pathname);
}
}
});
}

function mapDirAll(dir, containSonDir) {
filepath_arr = [];
if (!containSonDir) {
containSonDir = false;
}
return new Promise((resolve, reject) => {
try {
mapDir(dir, containSonDir);
} catch (e) {
reject(e);
}
resolve(filepath_arr);
});
}

exports.mapDirAll = mapDirAll;

调用

1
2
3
4
5
6
7
const { mapDirAll } = require("../utils/fileutil");
let basepath = "C:\\Users\\16798\\Documents\\conf.d\\";
let stats = fs.statSync(basepath);
if (stats.isDirectory()) {
let filepath_arr = await mapDirAll(basepath,false);
console.info("filepath_arr:", filepath_arr);
}

路径操作

获取路径文件名

path.basename(path[, ext])
获取路径中的文件名+文件扩展名
如果设置第二个参数表示过滤“.扩展名”,只要文件名称

示例:

1
2
3
4
5
6
7
8
const path = require('path');
var parseUrl = path.parse(url);
var basename1 = path.basename('/news/beijing/focus.html');
// 返回: 'focus.html'
console.log(basename1);
var basename2 = path.basename('/news/beijing/focus.htmll', '.html');
console.log(basename2);
//focus

获取路径中目录名

path.dirname() 方法返回 path 的目录名,类似于 Unix 的 dirname 命令。 尾部的目录分隔符将被忽略,参阅 path.sep。

1
2
3
var parseUrl = path.parse(url);
path.dirname('/foo/bar/baz/asdf/a.exe');
// 返回: '/foo/bar/baz/asdf'

路径分割符

path.sep 路径分割符
提供平台特定的路径片段分隔符:

Windows 上是 \。
POSIX 上是 /。

1
2
3
4
5
6
7
8
//例如,在 POSIX 上:
var parseUrl = path.parse(url);
'foo/bar/baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']

//在 Windows 上:
'foo\\bar\\baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']

获取当前文件的 根目录

1
2
global.appRoot = path.resolve(__dirname);
//C:\Users\ThinkPad\Desktop\webnode

注意

__dirname当前目录

__filename当前文件绝对路径

文件重命名

同步

1
2
const fs = window.require("fs");
fs.renameSync(new_file_path, old_file_path)

异步

1
2
3
4
5
6
7
const fs = window.require("fs");
ar fs = require('fs');

fs.rename('sample.txt', 'sample_old.txt', function (err) {
if (err) throw err;
console.log('File Renamed.');
});