打开manifest.json,在App权限配置中,添加读取和写入的权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
方法一:
files.js代码
/*
使用该类应开启以下权限(读取和写入)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
*/
/*
文件编码
ansi(ascii):英文标准码0-127,包括控制符和其他英文字符编码,这在后来一直统一没再变过,当然它只需要一个字节保存
gb2312和gbk:这两个是ancii码加上汉字的扩展,汉字多达10万,在ancii编码基础上再加一个字节表示汉字,共可表示字符65535个,包括了繁体字。因此一个中文字符包含两个字节。eclipse中默认编码方式为gbk。在Windows中文系统中ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码。
Unicode编码:顾名思义,这是国际统一标准编码,在这之前各国标准编码不统一,微软等公司需要为各国的计算机系统定制符合不同编码标准的系统,显然,成本太高,并且互联网的出现让不同编码标准的计算机交互变得困难,如:两国的邮件系统,会因为使用不同的编码标准而导致接受方收到的邮件是乱码。
utf-8和utf-16编码:UTF的意思是(UCS Transfer Format),显然是随着互联网的出现,需要解决Unicode在网络上的传输问题。顾名思义,UTF8就是每次8个位传输数据,而UTF16就是每次16个位,只不过为了传输时的可靠性,从UNICODE到UTF时并不是直接的对应,而是要过一些算法和规则来转换。UTF-8就是在互联网上使用最广的一种unicode的实现方式。
*/
/**
* 获取手机内置存储的根路径
* 路径 -(~\内部存储\Android\data\io.dcloud.HBuilder)
* @return {String}
*/
const root = function(folder) {
// 安卓10以下路径地址
//const environment = plus.android.importClass("android.os.Environment");
//return environment.getExternalStorageDirectory();
//兼容安卓10+ (通用)- 路径最好为"_downloads/",否则在手机中找不到路径
const localFile = plus.io.convertLocalFileSystemURL("_downloads/");
return localFile;
}
/**
* 获取指定文件夹下的所有文件和文件夹列表
* @param {String} path 文件夹路径
* @return {Array<String>} 文件和文件夹列表
*/
const filelist = function(dir = '') {
const File = plus.android.importClass("java.io.File");
let list = [];
let file = new File(dir);
let tempList = file.listFiles();
for (let i = 0; i < tempList.length; i++) {
let fileName = tempList[i].getName();
list.push(fileName);
}
return list;
}
/**
* 创建文件
* @return {boolean} flase=失败(已存在、操作失败),true=成功
*/
const createNewFile = function(path = '') {
const File = plus.android.importClass('java.io.File');
let file = new File(path);
if (!file.exists()) {
return file.createNewFile();
}
return false;
}
/**
* 创建文件夹
* @return {boolean} flase=失败(已存在、操作失败),true=成功
*/
const mkdirs = function(path = ''){
const File = plus.android.importClass('java.io.File');
let file = new File(path);
if (!file.exists()) {
return file.mkdirs();
}
return false;
}
/**
* 读取文件
* @param {String} path 文件路径
* @param {String} charset 编码
* @return {Array<String>} 内容列表(按行读取),文件不存在或异常则返回false
*/
const readTxt = function(path = '', charset = 'utf-8') {
const File = plus.android.importClass('java.io.File');
const InputStreamReader = plus.android.importClass('java.io.InputStreamReader');
const BufferedReader = plus.android.importClass('java.io.BufferedReader');
const FileInputStream = plus.android.importClass('java.io.FileInputStream');
let file = new File(path);
let inputStreamReader = null;
let bufferedReader = null;
let list = [];
try {
if (!file.exists()) {
return false;
}
inputStreamReader = new InputStreamReader(new FileInputStream(file), charset);
bufferedReader = new BufferedReader(inputStreamReader);
let line = '';
while (null != (line = bufferedReader.readLine())) {
list.push(line);
}
bufferedReader.close();
inputStreamReader.close();
} catch (e) {
if (null != bufferedReader) {
bufferedReader.close();
}
if (null != inputStreamReader) {
inputStreamReader.close();
}
return false;
}
return list;
}
/**
* 写入文件内容
* @param {String} path 文件路径
* @param {String} content 内容
* @param {boolean} append 内容写入类型,false=不追加(覆盖原有内容),true=追加(从内容尾部写入)
* @param {String} charset 编码
* @return {boolean} true=成功,false=失败
*/
const writeTxt = function(path = '', content = '', append = false, charset = 'utf-8') {
const File = plus.android.importClass('java.io.File');
const FileOutputStream = plus.android.importClass('java.io.FileOutputStream');
const OutputStreamWriter = plus.android.importClass('java.io.OutputStreamWriter');
var outputStreamWriter;
try{
// 创建文件夹和文件
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, fs => {
fs.root.getFile(path, {
create: true
});
});
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(path, append), charset);
outputStreamWriter.write(content);
outputStreamWriter.close();
} catch (e) {
if (null != outputStreamWriter) {
outputStreamWriter.close();
}
return false;
}
return true;
// 创建不来文件夹,不好使
/* let file = new File(path);
try {
//不存在则创建新的文件
if (!file.exists()) {
// 创建文件夹
file.mkdirs();
if(file.exists){
// file.createNewFile() 创建文件夹创建不了
let fileName = new File("demo.json");
fileName.createNewFile();
}
}
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(path, append), charset);
outputStreamWriter.write(content);
outputStreamWriter.close();
} catch (e) {
if (null != outputStreamWriter) {
outputStreamWriter.close();
}
return false;
}
return true; */
}
/**
* 判断文件是否存在
* @param path 文件路径
* @return true=存在 false=不存在
*/
const isFileExist = function(path = ''){
const File = plus.android.importClass('java.io.File');
return new File(path).exists()
}
/**
* 删除文件
* @param {String} path
*/
const deleteFile = function(path = ''){
const File = plus.android.importClass('java.io.File');
let file = new File(path);
if (file.exists()) {
return file.delete();
}
return false
}
export default {
root,
filelist,
createNewFile,
mkdirs,
readTxt,
writeTxt,
isFileExist,
deleteFile
}
使用方法:
import FileJS from '@/utils/files.js';//引用方法
// 获取文件路径
const filePaths = FileJS.root()+'/demo/dd.json';
// 获取要写入的内容
const content = data;
// 写入文件
const result = FileJS.writeTxt(filePaths, content);
// 如果写入成功
if (result) {
console.log("文件写入成功",filePaths);
} else {
console.error("文件写入失败");
}
// 读取文件内容
const readData = FileJS.readTxt(filePaths)
console.log("readData"readData);
方法二:
应用私有资源目录,对应常量plus.io.PRIVATE_WWW,仅应用自身可读
应用私有文档目录,对应常量plus.io.PRIVATE_DOC,仅应用自身可读写
应用公共文档目录,对应常量plus.io.PUBLIC_DOCUMENTS,多应用时都可读写,常用于保存应用间共享文件
应用公共下载目录,对应常量plus.io.PUBLIC_DOWNLOADS,多应用时都可读写,常用于保存下载文件常量:
PRIVATE_WWW: 应用私有资源目录常量
PRIVATE_DOC: 应用私有文档目录常量
PUBLIC_DOCUMENTS: 应用公共文档目录常量
PUBLIC_DOWNLOADS: 应用公共下载目录常量方法:
requestFileSystem: 请求本地文件系统对象
resolveLocalFileSystemURL: 通过URL参数获取目录对象或文件convertLocalFileSystemURL: 将本地URL路径转换成平台绝对路径
convertAbsoluteFileSystem: 将平台绝对路径转换成本地URL路
getAudioInfo: 获取音频文件信息
getFileInfo: 获取文件信息
getImageInfo: 获取图片信息
getVideoInfo: 获取视频文件信息
toolFile.js:
// 读取json文件
function getJsonData(path) { //path:路径
console.log("getData");
return new Promise(resolve => { //文件读写是一个异步请求 用promise包起来方便使用时的async+await
plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, fs => { //请求文件系统
fs.root.getFile(
path, { //请求地址文件 '/storage/emulated/0/config.txt'为根目录 '/config.txt'为/storage/Android/data/io.dcloud.HBuilder(包名)/documents/config.js
create: true //当文件不存在时创建
}, fileEntry => {
fileEntry.file(function(file) {
let fileReader = new plus.io
.FileReader(); //new一个可以用来读取文件的对象fileReader
fileReader.readAsText(file, "utf-8"); //读文件的格式
fileReader.onerror = e => { //读文件失败
console.log("获取文件失败", fileReader.error);
plus.nativeUI.toast("获取文件失败,请重启应用", {
background: "rgba(255, 255, 255, 0.6)",
});
return;
};
fileReader.onload = e => { //读文件成功
console.log("读取文件成功");
let txtData = e.target.result;
// console.log(txtData);
resolve(txtData); //回调函数内的值想返回到函数外部 就用promise+resolve来返回出去
};
});
}, error => {
console.log("2新建获取文件失败", error);
plus.nativeUI.toast("获取文件失败,请重启应用", {
background: "rgba(255, 255, 255, 0.6)",
});
return;
});
},
e => {
console.log("1请求文件系统失败", e.message);
plus.nativeUI.toast("请求系统失败,请重启应用", {
background: "rgba(255, 255, 255, 0.6)",
});
return;
}
);
});
};
// 写入josn文件
function changeData(path, seek, writeData) { //参数1:上传路径,参数2:seek方法可设置文件操作指定位置,参数3:写入的json数据
return new Promise(resolve => {
// resolveLocalFileSystemURL requestFileSystem PUBLIC_DOCUMENTS PRIVATE_DOC
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, fs => {
fs.root.getFile(path, {
create: true
}, fileEntry => {
fileEntry.file(file => {
fileEntry.createWriter(writer => {
console.log(fs.root.toURL(),'写入路径')
plus.nativeUI.showWaiting("正在保存信息");
writer.seek(seek); //覆盖文件
// 对象转成json字符串
/* const writeDataTemp = JSON.stringify(writeData, null,
"\r").replace(/[\r]/g, ""); */
writer.write(writeData); // 整个文件重写
writer.onerror = function() {
console.log("写入文件失败", writer.error.message);
plus.nativeUI.closeWaiting();
plus.nativeUI.toast("修改信息失败,请重新操作", {
background: "rgba(255, 255, 255, 0.6)",
});
return;
};
writer.onsuccess = function() { //填写文件成功
plus.nativeUI.closeWaiting();
plus.nativeUI.toast("保存成功", {
// background: "rgba(255, 255, 255, 0.6)",
});
resolve("1");
};
},
error => {
console.log("3创建creactWriter失败", error);
plus.nativeUI.toast("保存文件失败,请重新操作", {
// background: "#ffa38c",
});
return;
});
});
},
error => {
console.log("2获取文件失败", error);
plus.nativeUI.toast("保存文件失败,请重新操作", {
// background: "#ffa38c",
});
return;
}
);
}, e => {
console.log("1请求文件系统失败", e.message);
plus.nativeUI.toast("请求系统失败,请重新操作", {
// background: "#ffa38c",
});
return;
});
});
}
/**
* 储存文件到指定的地址:把一个文件移动到另外一个位置 剪切文件 重命名文件
* @param {String} url 新的地址 _doc/ 开头
* @param {String} file 原文件地址
* @param {String} newfilename 新的文件名
*/
async function saveFile(url, file, newfilename) {
let c = await creatDirs(url)
let isokm = moveDirectyOrFile(file, url + "/", newfilename);
return isokm
}
//循环创建目录 url:"_doc/...." _doc开头
async function creatDirs(url) {
let urllist = url.split("/");
console.log(urllist)
//创建文件夹
let u = "";
for (let i = 0; i < urllist.length - 1; i++) {
let j = i;
if (i == 0) {
u = urllist[i];
} else {
u = u + "/" + urllist[i];
}
console.log(i + "-------------------")
console.log(u)
console.log(urllist[j + 1])
await CreateNewDir(u, urllist[j + 1]);
}
}
//重命名目录或文件名
function moveDirectyOrFile(srcUrl, dstUrl, newName) { //srcUrl需要移动的目录或文件,dstUrl要移动到的目标目录(父级)
plus.io.resolveLocalFileSystemURL(srcUrl, function(srcEntry) {
//console.log(111)
plus.io.resolveLocalFileSystemURL(dstUrl, function(dstEntry) {
//console.log(222)
if (srcEntry.isDirectory) {
//console.log(33)
srcEntry.moveTo(dstEntry, newName, function(entry) {
//console.log("New Path: " + entry.fullPath);
return true;
}, function(e) {
return e;
//console.log(e.message);
});
} else {
srcEntry.moveTo(dstEntry, newName, function(entry) {
//console.log("New Path: " + entry.fullPath);
return true;
}, function(e) {
return e;
//console.log(e.message);
});
}
}, function(e) {
uni.showToast({
title: '获取目标目录失败:' + e.message,
duration: 2000,
icon: 'none'
});
});
}, function(e) {
uni.showToast({
title: '获取目录失败:' + e.message,
duration: 2000,
icon: 'none'
});
});
}
//创建一个新目录
function CreateNewDir(url, dirName) {
//url值可支持相对路径URL、本地路径URL
return new Promise((resolver, reject) => {
plus.io.resolveLocalFileSystemURL(url, function(entry) {
entry.getDirectory(dirName, {
create: true,
exclusive: false
}, function(dir) {
resolver(true)
}, function(error) {
reject(error.message)
uni.showToast({
title: dirName + '目录创建失败:' + error.message,
duration: 2000,
icon: 'none'
});
});
}, function(e) {
reject(error.message)
uni.showToast({
title: '获取目录失败:' + e.message,
duration: 2000,
icon: 'none'
});
});
})
}
/**
* 复制文件
* @param {String} url 文件地址,文件路径,最好是相对路径 url:"_doc/...." _doc开头
* @param {String} newUrl 目标目录,最好是相对路径 url:"_doc/...." _doc开头
* @param {String} newName 拷贝后的文件名称,默认为原始文件名称
*/
function copyFileTo(url, newUrl, dirName, newName) {
if (url.length >= 7 && "file://" == url.substring(0, 7)) {
url = url.substring(7)
}
let tempUrl = url.substring(0, url.lastIndexOf('/'));
let addUrl = newUrl + '/' + dirName;
console.log(addUrl, tempUrl)
if (addUrl == tempUrl) {
return url;
}
console.log(newUrl, dirName, newName)
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(url, async (entry) => {
if (entry.isFile) {
let c = await CreateNewDir(newUrl, dirName)
let u = await getDirsys(addUrl)
entry.copyTo(u, newName, en => {
resolve(en.fullPath);
}, e => {
console.log(e);
reject('错误:复制时出现错误')
uni.showModal({
title: "错误",
content: "复制时出现错误"
})
})
} else {
reject('错误:路径必须是文件')
uni.showModal({
title: "错误",
content: "路径必须是文件"
})
}
}, (e) => {
console.log(e);
reject(e)
uni.showModal({
title: "错误",
content: "打开文件系统时出错"
})
});
})
}
//获取目录对象
function getDirsys(url) {
return new Promise((resolve, reject) => {
plus.io.resolveLocalFileSystemURL(url, (entry) => {
resolve(entry)
}, (e) => {
reject(e)
console.log(e);
});
})
}
//将这些方法暴露出去
export {
getJsonData,
changeData,
saveFile,
creatDirs,
moveDirectyOrFile,
copyFileTo,
getDirsys,
};
使用方法:
import {getJsonData,changeData} from '@/utils/toolFile.js';//引用方法
//兼容安卓10+ (通用)- 路径最好为"_downloads/",否则在手机中找不到路径
const pathUrl = plus.io.convertLocalFileSystemURL("_downloads/") + 'feature.json'
//安卓10以下路径地址 安卓10+ pathUrl2 会报targetSdkVersion设置>=29后在Android10+系统设备不支持当前路径。请更改为应用运行路径
//const pathUrl2 = '/storage/emulated/0/' + 'demo.json'
/**
* 写入方法
* pathUrl - 上传路径
* 0
* 全局变量数据
*/
changeData(pathUrl, 0, data);
// 读取方法
getJsonData(pathUrl).then(data=>{
console.log("data",data);
})