ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Autojs基础-文件系统(files)

Autojs基础-文件系统(files) 1.前言脚本开发过程中考虑成本等多种因素不会配置云端数据库。我们可以将数据通过文件系统保存到本地txt文件当我们需要数据时再通过文件系统取出。除了保存基本文件外我们也可以将脚本图片等资源在脚本初次启动时加载到本地。文件系统在每个脚本中的使用方式类似操作简单但是非常重要。2.函数1.概况我们一般是操作sdcard文件下的文件sdcard文件夹相当于/storage/emulated/0文件夹两者是等价的。但是我看到一些地方说sdcard文件夹有些情况下不可以不如/storage/emulated/0兼容性好。因此我一般使用/storage/emulated/0文件夹。说实话我真没有发现两者有什么区别好在我们常操作文件夹是固定的。如果在Android中看过应用sdcard文件夹会发现应用文件夹很有特点。我们可以通过com名称功能或游戏名称的方式进行命名因为这是学习阶段我的常用文件夹就是com.py.test。文件夹全部路径为/storage/emulated/0/com.py.test/可以在脚本开始时全局保存。2.isFile判断文件路径为文件需要传递路径一个参数参数类型为字符串返回类型为boolean。需要注意的是如果文件不存在时也会返回false。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; console.log( 路径存在并且为文件 files.isFile(fileRootPath test.txt)); console.log( 路径存在并且为文件夹 files.isFile(fileRootPath)); console.log( 路径不存在并且为文件 files.isFile(fileRootPath test2.txt));3.isDir判断文件路径为文件夹需要传递路径一个参数参数类型为字符串返回类型为boolean。需要注意的是如果文件夹不存在时也会返回false。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; console.log( 路径存在并且为文件夹 files.isDir(fileRootPath)); console.log( 路径存在并且为文件 files.isDir(fileRootPath test.txt)); console.log( 路径不存在并且为文件夹 files.isDir(fileRootPath test2/));4.isEmptyDir判断文件夹是否为空文件夹需要传递文件夹路径一个参数参数类型为字符串返回类型为boolean。需要注意的是如果文件夹不存在时也会返回false。这个函数使用之前最好先通过exists函数判断路径是否存在当存在时再调用此函数。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; console.log( 路径存在并且为空文件夹 files.isEmptyDir(fileRootPath test/)); console.log( 路径存在并且为非空文件夹 files.isEmptyDir(fileRootPath)); console.log( 路径存在并且为文件 files.isEmptyDir(fileRootPath test.txt)); console.log( 路径不存在并且为文件夹 files.isEmptyDir(fileRootPath test2/));5.join将父路径与子路径进行拼接需要传递两个参数分别为父目录路径和子路径参数类型均为字符串返回拼接后的路径返回类型为字符串。有些小伙伴可能认为这个函数和直接使用“”进行字符串拼接一个功能。其实两者还是有点区别的这个函数能够自动忽略路径上多余的“/”或者加上少的“/”。console.log(files.join(/storage/emulated/0/com.py.test, test.txt)); console.log(files.join(/storage/emulated/0/com.py.test/, /test.txt));6.create与createWithDirscreate和createWithDirs均是用于创建文件或文件夹均需要传递路径一个参数均返回文件或文件夹是否创建成功返回类型均为boolean。如果路径上的文件夹都存在创建文件夹时不包含最后一个时两个函数宫那个一致。当路径上存在一个或者多个未创建的文件夹创建文件夹时不包含最后一个时create函数会创建失败而createWithDirs函数会将路径上所有的文件夹创建创建文件夹时不包含最后一个然后再创建最后一个文件或者文件夹。可以看出createWithDirs函数功能更加强大create函数通常先通过exists函数判断路径是否存在再进行调用。虽然createWithDirs函数功能强大但是很多时候输入错误路径时也会创建出文件来但是使用createWithDirs函数时要保证路径一定不要出错。综合来看两个函数各有优缺点两者频率差距不大。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; // 文件夹是否存在 console.log(当前文件夹是否存在 files.exists(fileRootPath)); console.log(create创建文件是否成功 files.create(fileRootPath test11.txt)); console.log(createWithDirs创建文件是否成功 files.createWithDirs(fileRootPath test12.txt)); console.log(-----------------------); let currentFolderPath fileRootPath test1/; console.log(当前文件夹是否存在 files.exists(currentFolderPath)); console.log(create创建文件是否成功 files.create(currentFolderPath test21.txt)); console.log(createWithDirs创建文件是否成功 files.createWithDirs(currentFolderPath test22.txt));7.exists判断文件或文件夹是否存在需要传递路径一个参数参数类型为字符串返回文件或文件是否存在返回类型为boolean。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test1/; console.log(test21文件是否存在 files.exists(currentFolderPath test21.txt)); console.log(test22文件是否存在 files.exists(currentFolderPath test22.txt));8.ensureDir确保路径中所有文件夹均存在需要传递路径一个参数参数类型为字符串。这个函数类似调用exists函数判断文件夹是否存在如果不存在调用createWithDirs函数来创建路径中所有的文件夹。其实文件系统中很多函数功能类似于多个函数的综合使用并且函数兼容性比较好函数一般能够兼容文件路径和文件夹路径。为什么说兼容性比较好以这个函数为例传递文件夹路径和文件路径均可以只确保文件路径中的所有文件夹均存在罢了不保证最后的文件存在。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test2/; console.log(当前文件夹是否存在 files.exists(currentFolderPath)); files.ensureDir(currentFolderPath); console.log(确保文件夹存在); console.log(当前文件夹是否存在 files.exists(currentFolderPath));9.read读取文件路径的文本内容需要传递两个参数分别为文件路径和字符编码默认为utf-8可以不传递参数类型均为字符串返回读取到的文件内容返回类型为字符串。我们保存的文件大部分情况下还有中文一般使用推荐的utf-8编码因此我建议大家将read当成只传递文件路径一个参数的函数。但是调用这个函数之前需要调用exists函数确保文件存在否则会报错。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test1/; let currentFilePath currentFolderPath test22.txt; // 如果文件存在 if (files.exists(currentFilePath)) { let fileContent files.read(currentFilePath); console.log(fileContent); console.log(类型为 (typeof fileContent)); }其实为了保证安全性除了调用exists函数保证路径存在外还需要调用isFile函数保证为文件。正常情况下我们不会去读取文件夹的内容只要保证路径存在即可但是防止特殊情况下报错而导致脚本停止最好加上个文件判断或者捕获一下读取文件的异常。但是我自己使用是只需要判断文件存在即可因为我能保证不会去读取文件夹的内容。这部分内容主要是为了让大家知道读取文件夹会出现下面报错如果出现这种报错可以找到方向。如果读取不存在文件的内容会出现以下报错10.readBytes通过字节的方式读取文件的内容需要传递文件路径一个参数参数类型为字符串返回读取到的字节数据返回类型为字节数组。这个函数中文件路径参数要求和read函数一致一定要保证路径存在且为文件。这个函数只有在特殊情况下使用比如某个操作文件的函数只接收字节数组类型的数据我们才使用readBytes函数读取数据然后直接传到操作函数中。我们自己读取文件内容肯定不会通过这种方式来读取远没有read函数方便。11.write将文本内容写入本地文件需要传递三个参数分别为文件路径、文本内容和字符编码默认为utf-8可以不传递参数类型均为字符串。由于中文写入文件概率很高我们可以将此函数默认只需要传递文件路径和文本内容两个参数。写入文件之前要保证这个文件已经存在并且写入方式为覆盖方式也就是说如果文件中有内容会先删除原来内容再写入新内容。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test1/; let currentFilePath currentFolderPath test22.txt; // 如果文件存在 if (files.exists(currentFilePath)) { let fileContent files.read(currentFilePath); console.log(文件初始内容为); console.log(fileContent); console.log(---------------); files.write(currentFilePath, 成功替换); fileContent files.read(currentFilePath); console.log(替换后新内容为); console.log(fileContent); }12.writeBytes将字节数据写入到本地文件中需要传递两个参数分别文件路径和字节数据参数类型分别为字符串和字节数组。文件路径要求和写入方式与write一致这是写入的内容不同。这个函数只有特殊情况下将文件写入本地时才会调用媒体文件居多。但是将文件写入本地的方式很多以图片为例图片处理模块有将图片直接保存到本地的函数肯定不会多此一举使用此函数。小伙伴们可以认为这个函数和readBytes函数一样只有特殊情况下才会使用至于啥时候为特殊情况需要自己判断。简言之这个函数和readBytes函数平时不要使用在没办法时有个考虑思路即可。13.append与appendBytesappend与appendBytes函数都是在文件中追加内容这个两个函数的区别与write和writeBytes函数类似只是追加方式不同罢了。append函数需要传递三个参数分别为文件路径、文件内容和字符编码默认为utf-8可以不传递参数类型均为字符串。由于中文写入文件概率很高我们可以将此函数默认只需要传递文件路径和文本内容两个参数。appendBytes函数需要传递两个参数分别为路径和字节数据参数类型分别为字符串和字节数组。只有特殊情况下才会使用。需要注意官方文档中函数上有三个参数但是详细中只有两个参数的介绍到底以哪个为主我通过测试发现这个函数确实是只能传递两个参数传递三个参数会报错可能官方文档上函数上参数没处理好。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test1/; let currentFilePath currentFolderPath test22.txt; // 如果文件存在 if (files.exists(currentFilePath)) { let fileContent files.read(currentFilePath); console.log(文件初始内容为); console.log(fileContent); console.log(---------------); let appendContent 追加内容; files.append(currentFilePath, appendContent); fileContent files.read(currentFilePath); console.log(追加后新内容为); console.log(fileContent); }虽然对这两个追加函数介绍很多但是我不推荐这两种方式。为了读取数据方便我们平时会将数组或者对象等数据保存文件中追加方式根本没用我更推荐是将文件中内容读取出来然后通过复杂操作后然后将最终字符串内容通过write函数写回文件中。哪怕真的用追加的方式可以完成操作我还是推荐采用全部读取字符串处理全部写回的方式完成。我感觉这个种方式看起来复杂真正的效率可能比写会效率更高。简言之append与appendBytes函数可以学习过程中使用脚本开发过程中没必要使用。但是这种追加的方式用来保存打印日志倒是一个不错的选择我看看有时间真得尝试下能不能自己弄个日志打印文件然后读取文件自己手搓一个日志悬浮窗。又说多了这是我灵光一现的想法但是感觉工作量不小有时间可以考虑一下。14.copy与movecopy函数用于将文件从一个文件夹复制到另一个文件夹需要传递两个参数分别为需要复制的源文件路径和复制到目标文件的路径参数类型均为字符串。move函数用于将文件从一个文件夹移动到另一个文件夹需要传递两个参数分别为需要移动的源文件路径和移动到目标文件的路径参数类型均为字符串。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; // 源文件路径 let currentFolderPath fileRootPath test1/; let currentFilePath currentFolderPath test22.txt; // 目标文件路径 let targetFolderPath fileRootPath test2/; let targetFilePath targetFolderPath test22副本.txt; // 源副本文件路径 let sourceCopyFilePath currentFolderPath test22副本.txt; // 文件状态打印 fileStatusLog(); console.log(---------------------); files.copy(currentFilePath, targetFilePath); console.log(完成复制); // 文件状态打印 fileStatusLog(); console.log(---------------------); files.move(targetFilePath, sourceCopyFilePath); console.log(完成移动); // 文件状态打印 fileStatusLog(); // 文件状态打印 function fileStatusLog() { console.log(源文件是否存在 files.exists(currentFilePath)); console.log(目标文件是否存在 files.exists(targetFilePath)); console.log(源副本文件是否存在 files.exists(sourceCopyFilePath)); }15.rename与renameWithoutExtensionrename和renameWithoutExtension函数均是用于修改文件名均需要传递两个参数分别为文件路径和新文件名。rename传递的新文件名需要包含文件后缀而renameWithoutExtension函数传递的新文件名不需要包含文件后缀。如果只需要改文件名可以调用renameWithoutExtension函数如果修改文件名和文件类型可以调用rename函数。// 保存文件总地址 let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test1/; let currentFilePath currentFolderPath test22副本.txt; // 获取当前文件夹所有文件 let fileList files.listDir(currentFolderPath); console.log(fileList); console.log(--------------); files.renameWithoutExtension(currentFilePath, test33); console.log(成功修改文件名); // 获取当前文件夹所有文件 fileList files.listDir(currentFolderPath); console.log(fileList); console.log(--------------); files.rename(currentFolderPath test33.txt, test44.txt); console.log(成功修改文件名和文件类型); // 获取当前文件夹所有文件 fileList files.listDir(currentFolderPath); console.log(fileList);16.getName、getNameWithoutExtension与getExtensiongetName、getNameWithoutExtension和getExtension函数均用于获取文件信息均需要传递文件路径一个参数参数类型均为字符串均返回字符串类型的数据。getName用于获取文件包含后缀的名称。getNameWithoutExtension用于获取文件不包含后缀的名称。getExtension用于获取文件后缀。let fileRootPath /storage/emulated/0/com.py.test/; let currentFilePath fileRootPath test1/test22.txt; // 如果文件存在 if (files.exists(currentFilePath)) { console.log(包含后缀的名称 files.getName(currentFilePath)); console.log(不包含后缀的名称 files.getNameWithoutExtension(currentFilePath)); console.log(文件后缀 files.getExtension(currentFilePath)); }17.remove与removeDirremove和removeDir函数均用于删除操作均需要传递路径一个参数参数类型均为字符串均返回是否操作成功返回类型均为boolean。remove用于删除文件或者空文件夹删除文件夹时需要写先判断文件夹是否为空。removeDir用于删除文件夹如果文件夹不为空会删除该文件夹下的所有内容再删除此文件夹。let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test2/; let fileList files.listDir(currentFolderPath); console.log(fileList); console.log(-----------------); console.log(是否成功删除单个文件 files.remove(currentFolderPath test44.txt)); fileList files.listDir(currentFolderPath); console.log(fileList); console.log(-----------------); console.log(是否成功删除文件夹 files.removeDir(currentFolderPath)); console.log(test2文件夹是否存在 files.exists(currentFolderPath));除了上面基础用法外大家应该比较关注要删除的文件夹中含有文件夹情况下removeDir函数是否生效。我通过测试发现需要删除的文件夹下如果嵌套多层文件夹也能成功删除。removeDir函数删除功能非常强大但是也得注意错误删除文件夹需要谨慎使用这个函数。推荐还是删除文件夹下所有文件后再删除空文件夹。18.getSdcardPath与cwdgetSdcardPath函数用于获取sd卡地址返回sd卡的地址返回类型为字符串。cwd函数用于返回当前工作路径返回当前工作路径地址返回类型为字符串。let sdcardPath files.getSdcardPath(); let workPath files.cwd(); console.log(sdcardPath); console.log(workPath);19.path返回相对路径对应的绝对路径需要传递相对路径一个参数参数类型为字符串返回绝对路径返回类型为字符串。其实这个函数作用就用cwd()函数路径替换相对路径“./”的内容。let absolutePath files.path(./文件系统/test.txt); console.log(absolutePath);读取相对路径文件时必须将整个项目保存到设备然后再进行启动。真正启动时会发现在设备上启动相对路径文件可以找到。但是在代码编辑器中启动时相对路径文件又无法找到。通过这个函数获取的绝对路径可以找到文件。let absolutePath files.path(./文件系统/test.txt); console.log(absolutePath); if (files.exists(absolutePath)) { let fileContent files.read(absolutePath); console.log(fileContent); }else { console.log(文件不存在); }但是通过path函数找到绝对路径开发时可以使用以“文件系统”项目为例打包时都在这个项目中打包打包时采用这种绝对路径方式必然失败应该采用相对路径方式打包。这样就出现了个问题如果采用相对路径方式需要在设备中启动项目如果采用path函数绝对路径打包后无法再次运行项目有个别小伙伴说我打包后也能找到文件这是因为设备中也有编辑器推送的代码在新设备中根本无法找到文件的。基于上面这种情况我们可以提前预制开发环境和生产环境对应的相对路径文件夹。然后赋值给当前相对路径relativeFolder变量以后都使用relativeFolder变量即可。如果环境改变时切换relativeFolder变量赋值即可。// 生产环境相对路径文件夹 let procRelativeFolder ./; // 项目名称根据实际情况替换 let projectName 文件系统; // 开发环境相对路径文件夹 let devRelativeFolder files.cwd() / projectName /; // 相对路径文件夹 // 开发时切换到开发环境 // 打包时切换到生产环境 // 读取相对路径文件时都采用这种方式 let relativeFolder procRelativeFolder; let absolutePath files.path(relativeFolder test.txt); console.log(absolutePath); if (files.exists(absolutePath)) { let fileContent files.read(absolutePath); console.log(fileContent); toast(fileContent); }else { console.log(文件不存在); }生产环境的相对路径是固定的开发环境每个项目需要修改对应的项目名称其他地方不用修改。项目名称其实是文件夹名称以下是代码编辑器和autojs中的项目名称可以在任意地方查看然后进行替换即可。20.listDir打印文件夹下所有文件带后缀的文件名称需要传递两个参数分别为文件夹路径和过滤函数可不传递参数类型分别为字符串和函数返回文件信息返回类型为数组。我不建议在这个函数中直接调用过滤函数我们可以先获取所有的文件信息然后通过js的数组过滤方法来获取需要的数据。let fileRootPath /storage/emulated/0/com.py.test/; let currentFolderPath fileRootPath test1/; if (files.exists(currentFolderPath)) { let fileList files.listDir(currentFolderPath); console.log(fileList); console.log(---------------------------); fileList files.listDir(currentFolderPath, function (fileName) { return fileName.startsWith(test2); }); console.log(fileList); console.log(---------------------------); // 相当于 fileList files.listDir(currentFolderPath); let filterList fileList.filter(function (fileName, index){ return fileName.startsWith(test2); }) console.log(filterList); }
返回列表