Electron常用路径及文件和文件夹操作

常用路径

程序安装文件夹路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const {app} = window.require("electron").remote;
const path = window.require("path");
const fs = window.require("fs");

let homeDir = path.dirname(app.getPath("exe"));

let mypath = path.join(
homeDir,
"_temp",
"个人空间"
);

try{
if (!fs.existsSync(mypath)) {
fs.mkdirSync(mypath, { recursive: true });
}
}catch (e) {}

其中homeDir的路径为:

  • 开发环境 D:\Project\Electron\school_live_client\node_modules\electron\dist\
  • 打包环境 安装目录中exe的同级目录

EXE路径

可执行文件路径

1
app.getPath("exe")

结果

app.getPath(“exe”): D:\Project\Electron\school_live_client\node_modules\electron\dist\electron.exe

注意:

这里是开发时打印的路径,发布后是不一样的,是安装后的文件夹路径+exe文件名称

用户相关文件夹路径

  • home 用户的 home 文件夹(主目录)
  • documents 用户文档目录的路径
  • downloads 用户下载目录的路径
  • music 用户音乐目录的路径
  • pictures 用户图片目录的路径
  • videos 用户视频目录的路径
1
2
3
4
5
6
app.getPath("home");
app.getPath("documents");
app.getPath("downloads");
app.getPath("music");
app.getPath("pictures");
app.getPath("videos");

结果

app.getPath(“home”): C:\Users\18351
app.getPath(“documents”): C:\Users\18351\Documents
app.getPath(“downloads”): C:\Users\18351\Downloads
app.getPath(“music”): C:\Users\18351\Music
app.getPath(“pictures”): C:\Users\18351\Pictures
app.getPath(“videos”): C:\Users\18351\Videos

注意:

这些路径中包含用户名,如果计算机的用户名是中文的话,路径中就会包含中文,有些第三方的库使用的路径可能不支持中文,一定要注意!!!

桌面文件夹路径

1
app.getPath("desktop")

结果

app.getPath(“desktop”): C:\Users\18351\Desktop

注意:

桌面路径中包含用户名,如果计算机的用户名是中文的话,路径中就会包含中文,有些第三方的库使用的路径可能不支持中文,一定要注意!!!

AppData下文件夹路径

  • appData 每个用户的应用程序数据目录,默认情况下指向
    • %APPDATA% Windows 中
    • $XDG_CONFIG_HOME or ~/.config Linux 中
    • ~/Library/Application Support macOS 中
  • userData 储存你应用程序设置文件的文件夹,默认是 appData 文件夹附加应用的名称
  • logs应用程序的日志文件夹
  • cache缓存路径
  • temp 临时文件夹

代码

1
2
3
4
5
app.getPath("appData");
app.getPath("userData");
app.getPath("logs");
app.getPath("cache");
app.getPath("temp");

结果

app.getPath(“appData”): C:\Users\18351\AppData\Roaming
app.getPath(“userData”): C:\Users\18351\AppData\Roaming\应用名称
app.getPath(“logs”): C:\Users\18351\AppData\Roaming\应用名称\Electron\logs
app.getPath(“cache”): C:\Users\18351\AppData\Roaming
app.getPath(“temp”): C:\Users\18351\AppData\Local\Temp

注意:

注意用户名应用名为中文的时候,logsuserData中会包含中文,有些第三方的库使用的路径可能不支持中文,一定要注意!!!

程序根目录(不建议)

不建议使用

1
2
const {app} = window.require("electron").remote;
app.getAppPath();

结果

app.getAppPath(): D:\Project\Electron\school_live_client

注意:

这个在开发时时源代码所在路径。

这是应用的安装路径和应用名称没有必然关系,一定要注意。

打包后的路径为

假如程序的安装路径为D:\MyApp

D:\MyApp\resources\app.asar

这个路径是在压缩文件内不建议使用。

不建议使用的路径

这两个路径会报错

  • recent 用户最近文件的目录 (仅限 Windows)。
  • crashDumps 崩溃转储文件存储的目录。

返回 String - 一个与 name相关的特殊目录或文件的路径。 失败会抛出一个Error

路径获取方法推荐

很多应用的应用存储位置在AppData下,但是有的程序不支持中文路径,而AppData可能包含中文。

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
const path = require("path");
const fs = require("fs");

global.sharedObject = {
appBasePath: "",
};

let basePath = "";

try {
//默认使用我的文档文件夹
basePath = app.getPath("documents");
} catch (e) {
//有问题使用程序安装路径
basePath = path.dirname(app.getPath("exe"));
}

//如果路径有中文则使用C盘根目录
if (/.*[\u4e00-\u9fa5 ]+.*$/.test(basePath)) {
basePath = "C:\\";
}

let appBasePath = path.join(basePath, "zmind_home");

//创建文件夹
try {
if (!fs.existsSync(appBasePath)) {
fs.mkdirSync(appBasePath, { recursive: true });
}
} catch (e) {
console.info(e);
}
global.sharedObject.appBasePath = appBasePath;

渲染进程获取参数参见

https://www.psvmc.cn/article/2023-09-13-electron-remote.html

获取文件夹下文件

获取文件夹及子文件夹下的文件,返回一层的文件路径的数组。

zfile_util.js

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
const path = require("path");
const fs = require("fs");
let filepathArr = [];
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, containSonDir);
}
} else if (stats.isFile()) {
let index = filename.lastIndexOf(".");
//获取后缀
let ext = filename.substr(index + 1);
if (ext === "txt") {
filepathArr.push(pathname);
}
}
});
}

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

exports.mapDirAll = mapDirAll;

调用

1
2
3
4
5
6
7
8
9
10
11
const { mapDirAll } = require("./nodejs_utils/zfile_util");
async function getAllPath() {
let stats = fs.statSync(appBasePath);
if (stats.isDirectory()) {
console.info(appBasePath);
let filepathArr = await mapDirAll(appBasePath, true);
console.info("filepathArr:", filepathArr);
}
}

getAllPath();

获取文件夹及子文件夹和文件

获取文件夹及子文件夹以及文件,返回树状结构。

zfile_util.js

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
42
43
44
45
46
47
48
49
50
const path = require("path");
const fs = require("fs");
let filepathArr = [];
function mapDir(dir, containSonDir, arr) {
let files = fs.readdirSync(dir);
files.forEach((filename) => {
let pathname = path.join(dir, filename);
let stats = fs.statSync(pathname);
if (stats.isDirectory()) {
let obj = {
name: filename,
path: pathname,
type: "folder",
children: [],
};
arr.push(obj);
if (containSonDir) {
mapDir(pathname, containSonDir, obj.children);
}
} else if (stats.isFile()) {
let index = filename.lastIndexOf(".");
//获取后缀
let ext = filename.substring(index + 1);
if (ext === "txt") {
arr.push({
name: filename,
path: pathname,
type: "file",
});
}
}
});
}

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

exports.mapDirAll = mapDirAll;

使用

1
2
3
4
5
6
7
8
9
10
11
const { mapDirAll } = require("./nodejs_utils/zfile_util");
async function getAllPath() {
let stats = fs.statSync(appBasePath);
if (stats.isDirectory()) {
console.info(appBasePath);
let filepathArr = await mapDirAll(appBasePath, true);
console.info("filepathArr:", JSON.stringify(filepathArr));
}
}

getAllPath();

文件弹窗保存

主进程

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
const { ipcMain } = require("electron");
const { dialog } = require("electron");
const path = require("path");

ipcMain.on("saveFile", (event, arg) => {
dialog
.showSaveDialog({
defaultPath: path.join(
global.sharedObject.appBasePath,
arg ? arg : "filename.txt"
), // 保存文件的默认路径和名称
})
.then((result) => {
if (!result.canceled) {
const filePath = result.filePath;
// 在这里执行保存文件的逻辑
console.log("保存路径:", filePath);
event.reply("saveFilePath", filePath);
} else {
console.log("取消保存文件");
}
})
.catch((err) => {
console.log("保存文件出错:", err);
});
});

渲染进程

1
2
3
4
5
6
const { ipcRenderer } = window.require("electron");

ipcRenderer.send("saveFile", "新脑图.txt");
ipcRenderer.on('saveFilePath', (event, arg) => {
console.log(arg)
})

文件读写

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

}
});

示例

1
2
3
4
5
6
7
8
function writeToFile(filePath, content) {
const fs = window.require("fs");
try {
fs.writeFileSync(filePath, content);
} catch (err) {
console.error(err);
}
}

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

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

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

您可能会使用的标志是

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