FileHelper.ets 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. import fileUri from '@ohos.file.fileuri';
  2. import fs from '@ohos.file.fs';
  3. import fileIo, { ListFileOptions, ReadOptions, ReadTextOptions, WriteOptions } from '@ohos.file.fs';
  4. import { BusinessError } from '@kit.BasicServicesKit';
  5. import { StrHelper } from './StrHelper';
  6. import { hilog } from '@kit.PerformanceAnalysisKit';
  7. import { image } from '@kit.ImageKit';
  8. import { buffer } from '@kit.ArkTS';
  9. import { LogHelper } from './LogHelper';
  10. import { ToolsHelper } from './ToolsHelper';
  11. import { photoAccessHelper } from '@kit.MediaLibraryKit';
  12. import { GlobalContext } from '../ContextConfig';
  13. export class FileHelper {
  14. private constructor() {
  15. }
  16. static readonly separator: string = '/';
  17. /**
  18. * 获取文件目录下的文件夹路径或文件路径。
  19. * @param dirPath 文件路径;支持完整路径和相对路径(download/wps/doc);dirPath传空字符串表示根目录
  20. * @param fileName 文件名(test.text);fileName传空字符串表示文件夹路径
  21. * @param blHap true:HAP级别文件路径、 false:App级别文件路径
  22. * @returns
  23. */
  24. static getFilesDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {
  25. let filePath = blHap ? getContext().filesDir : getContext().getApplicationContext().filesDir; //根目录
  26. if (StrHelper.isNotEmpty(dirPath)) {
  27. if (StrHelper.startsWith(dirPath, filePath)) { //路径中包含根目录,是完整路径。
  28. filePath = dirPath;
  29. } else { //路径中不包含根目录,拼接成完整路径。
  30. filePath = filePath + FileHelper.separator + dirPath;
  31. }
  32. if (!FileHelper.accessSync(filePath)) {
  33. FileHelper.mkdirSync(filePath) //如果文件夹不存在就创建
  34. }
  35. }
  36. if (StrHelper.isNotEmpty(fileName)) {
  37. filePath = filePath + FileHelper.separator + fileName;
  38. }
  39. return filePath;
  40. }
  41. /**
  42. * 获取缓存目录下的文件夹路径或文件路径。
  43. * @param dirPath 文件路径;支持完整路径和相对路径(download/wps/doc);dirPath传空字符串表示根目录
  44. * @param fileName 文件名(test.text);fileName传空字符串表示文件夹路径
  45. * @param blHap true:HAP级别文件路径、 false:App级别文件路径
  46. * @returns
  47. */
  48. static getCacheDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {
  49. let filePath = blHap ? getContext().cacheDir : getContext().getApplicationContext().cacheDir; //根目录
  50. if (StrHelper.isNotEmpty(dirPath)) {
  51. if (FileHelper.hasDirPath(dirPath)) { //路径中包含根目录,是完整路径。
  52. filePath = dirPath;
  53. } else { //路径中不包含根目录,拼接成完整路径。
  54. filePath = filePath + FileHelper.separator + dirPath;
  55. }
  56. if (!FileHelper.accessSync(filePath)) {
  57. FileHelper.mkdirSync(filePath) //如果文件夹不存在就创建
  58. }
  59. }
  60. if (StrHelper.isNotEmpty(fileName)) {
  61. filePath = filePath + FileHelper.separator + fileName;
  62. }
  63. return filePath;
  64. }
  65. /**
  66. * 获取临时目录下的文件夹路径或文件路径。
  67. * @param dirPath 文件路径;支持完整路径和相对路径(download/wps/doc);dirPath传空字符串表示根目录
  68. * @param fileName 文件名(test.text);fileName传空字符串表示文件夹路径
  69. * @param blHap true:HAP级别文件路径、 false:App级别文件路径
  70. * @returns
  71. */
  72. static getTempDirPath(dirPath: string = "", fileName: string = "", blHap: boolean = true): string {
  73. let filePath = blHap ? getContext().tempDir : getContext().getApplicationContext().tempDir; //根目录
  74. if (StrHelper.isNotEmpty(dirPath)) {
  75. if (FileHelper.hasDirPath(dirPath)) { //路径中包含根目录,是完整路径。
  76. filePath = dirPath;
  77. } else { //路径中不包含根目录,拼接成完整路径。
  78. filePath = filePath + FileHelper.separator + dirPath;
  79. }
  80. if (!FileHelper.accessSync(filePath)) {
  81. FileHelper.mkdirSync(filePath) //如果文件夹不存在就创建
  82. }
  83. }
  84. if (StrHelper.isNotEmpty(fileName)) {
  85. filePath = filePath + FileHelper.separator + fileName;
  86. }
  87. return filePath;
  88. }
  89. /**
  90. * 判断是否是完整路径
  91. * @param path 文件路径
  92. */
  93. static hasDirPath(path: string): boolean {
  94. return StrHelper.startsWith(path, "/data/storage/el1/") || StrHelper.startsWith(path, "/data/storage/el2/");
  95. }
  96. /**
  97. * 通过URI或路径,获取FileUri
  98. * @param uriOrPath URI或路径
  99. * @returns
  100. */
  101. static getFileUri(uriOrPath: string): fileUri.FileUri {
  102. return new fileUri.FileUri(uriOrPath);
  103. }
  104. /**
  105. * 通过URI或路径,获取文件名。
  106. * @param uriOrPath URI或路径
  107. * @returns
  108. */
  109. static getFileName(uriOrPath: string): string {
  110. return FileHelper.getFileUri(uriOrPath).name;
  111. }
  112. /**
  113. * 通过URI或路径,获取文件路径
  114. * @param uriOrPath URI或路径
  115. * @returns
  116. */
  117. static getFilePath(uriOrPath: string): string {
  118. return FileHelper.getFileUri(uriOrPath).path;
  119. }
  120. /**
  121. * 通过URI或路径,获取对应文件父目录的URI。
  122. * @param uriOrPath URI或路径
  123. */
  124. static getParentUri(uriOrPath: string): string {
  125. return FileHelper.getFileUri(uriOrPath).getFullDirectoryUri();
  126. }
  127. /**
  128. * 通过URI或路径,获取对应文件父目录的路径名。
  129. * @param uriOrPath URI或路径
  130. */
  131. static getParentPath(uriOrPath: string): string {
  132. let parentUri = FileHelper.getParentUri(uriOrPath);
  133. return FileHelper.getFilePath(parentUri)
  134. }
  135. /**
  136. * 以同步方法获取文件URI。
  137. * @param path 应用沙箱路径
  138. * @returns
  139. */
  140. static getUriFromPath(path: string): string {
  141. return fileUri.getUriFromPath(path);
  142. }
  143. /**
  144. * 根据文件名获取文件后缀
  145. * @param fileName 例如: test.txt test.doc
  146. * @returns
  147. */
  148. static getFileExtention(fileName: string) {
  149. if (StrHelper.isNotEmpty(fileName) && fileName.includes(".")) {
  150. return fileName.substring(fileName.lastIndexOf(".") + 1);
  151. }
  152. return '';
  153. }
  154. /**
  155. * 获取指定文件夹下所有文件的大小或指定文件大小。
  156. * @param path 文件夹路径 或 文件路径
  157. */
  158. static getFileDirSize(path: string): number {
  159. if (FileHelper.accessSync(path)) { //path存在
  160. if (FileHelper.isDirectory(path)) { //文件夹
  161. let count: number = 0;
  162. FileHelper.listFileSync(path, { recursion: true }).forEach((filePath) => {
  163. count = count + FileHelper.lstatSync(path + filePath).size
  164. })
  165. return count;
  166. } else { //文件
  167. return FileHelper.lstatSync(path).size
  168. }
  169. }
  170. return 0;
  171. }
  172. /**
  173. * 判断文件是否是普通文件。
  174. * @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
  175. * @returns
  176. */
  177. static isFile(file: string | number): boolean {
  178. return fs.statSync(file).isFile();
  179. }
  180. /**
  181. * 判断文件是否是目录。
  182. * @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
  183. * @returns
  184. */
  185. static isDirectory(file: string | number): boolean {
  186. return fs.statSync(file).isDirectory();
  187. }
  188. /**
  189. * 重命名文件或文件夹,使用Promise异步回调。
  190. * @param oldPath string 文件的应用沙箱原路径。
  191. * @param newPath string 文件的应用沙箱新路径。
  192. * @returns
  193. */
  194. static rename(oldPath: string, newPath: string): Promise<void> {
  195. return fs.rename(oldPath, newPath);
  196. }
  197. /**
  198. * 重命名文件或文件夹,以同步方法。
  199. * @param oldPath string 文件的应用沙箱原路径。
  200. * @param newPath string 文件的应用沙箱新路径。
  201. * @returns
  202. */
  203. static renameSync(oldPath: string, newPath: string) {
  204. fs.renameSync(oldPath, newPath);
  205. }
  206. /**
  207. * 创建目录,当recursion指定为true,可多层级创建目录,使用Promise异步回调。
  208. * @param path 目录的应用沙箱路径。
  209. * @param recursion 是否多层级创建目录。recursion指定为true时,可多层级创建目录。recursion指定为false时,仅可创建单层目录。
  210. * @returns
  211. */
  212. static mkdir(path: string, recursion: boolean = true): Promise<void> {
  213. if (recursion) {
  214. return fs.mkdir(path, recursion);
  215. } else {
  216. return fs.mkdir(path);
  217. }
  218. }
  219. /**
  220. * 创建目录以同步方法,当recursion指定为true,可多层级创建目录。
  221. * @param path 目录的应用沙箱路径。
  222. * @param recursion 是否多层级创建目录。recursion指定为true时,可多层级创建目录。recursion指定为false时,仅可创建单层目录。
  223. */
  224. static mkdirSync(path: string, recursion: boolean = true) {
  225. if (recursion) {
  226. fs.mkdirSync(path, recursion);
  227. } else {
  228. fs.mkdirSync(path);
  229. }
  230. }
  231. /**
  232. * 删除整个目录,使用Promise异步回调。
  233. * @param path 目录的应用沙箱路径。
  234. * @returns
  235. */
  236. static rmdir(path: string): Promise<void> {
  237. return fs.rmdir(path);
  238. }
  239. /**
  240. * 删除整个目录,以同步方法。
  241. * @param path 目录的应用沙箱路径。
  242. */
  243. static rmdirSync(path: string) {
  244. return fs.rmdirSync(path);
  245. }
  246. /**
  247. * 删除单个文件,使用Promise异步回调。
  248. * @param path 文件的应用沙箱路径。
  249. * @returns
  250. */
  251. static unlink(path: string): Promise<void> {
  252. return fs.unlink(path);
  253. }
  254. /**
  255. * 删除单个文件,以同步方法。
  256. * @param path 文件的应用沙箱路径。
  257. * @returns
  258. */
  259. static unlinkSync(path: string) {
  260. fs.unlinkSync(path);
  261. }
  262. /**
  263. * 检查文件是否存在,使用Promise异步回调。
  264. * @param path 文件应用沙箱路径。
  265. * @returns
  266. */
  267. static access(path: string): Promise<boolean> {
  268. return fs.access(path);
  269. }
  270. /**
  271. * 检查文件是否存在,以同步方法。
  272. * @param path 文件应用沙箱路径。
  273. * @returns
  274. */
  275. static accessSync(path: string): boolean {
  276. return fs.accessSync(path);
  277. }
  278. static getFileFd(uri: string) {
  279. let file = FileHelper.openSync(uri, fs.OpenMode.READ_ONLY)
  280. return file.fd
  281. }
  282. /**
  283. * 图片转base64
  284. * @param photoUri
  285. * @returns
  286. */
  287. static BmpToBase64(photoUri: string): Promise<string> {
  288. const imagePackerApi: image.ImagePacker = image.createImagePacker();
  289. const packOpts: image.PackingOption = { format: 'image/jpeg', quality: 100 };
  290. return new Promise<string>((resolve, reject) => {
  291. let file = FileHelper.openSync(photoUri, fs.OpenMode.READ_ONLY)
  292. const imageSource = image.createImageSource(file.fd);
  293. LogHelper.error('file.fd:' + file.fd)
  294. imageSource.createPixelMap().then((pixelMap) => {
  295. imagePackerApi.packing(pixelMap, packOpts).then((data: ArrayBuffer) => {
  296. let buf: buffer.Buffer = buffer.from(data);
  297. LogHelper.error('data:' + data)
  298. resolve(buf.toString('base64'))
  299. }).catch((err: BusinessError) => {
  300. LogHelper.error('packing failed with err: ' + JSON.stringify(err));
  301. reject(err)
  302. })
  303. }).catch((err: BusinessError) => {
  304. LogHelper.error('createPixelMap failed with err: ' + JSON.stringify(err));
  305. reject(err)
  306. });
  307. })
  308. }
  309. /**
  310. * 保存图片到相册,需要注意权限
  311. * @param pixmap
  312. */
  313. static saveImage(pixmap: image.PixelMap): Promise<string> {
  314. return new Promise<string>(async (resolve, reject) => {
  315. let imageBuffer: ArrayBuffer = new ArrayBuffer(1);
  316. try {
  317. imageBuffer = await image.createImagePacker().packing(pixmap, { format: "image/png", quality: 100 });
  318. } catch (err) {
  319. ToolsHelper.showMessage('保存失败');
  320. console.error(`Invoke packingPixelMap2Jpg failed, err: ${JSON.stringify(err)}`);
  321. reject()
  322. return;
  323. }
  324. const uri = await photoAccessHelper.getPhotoAccessHelper(GlobalContext.getContext())
  325. .createAsset(photoAccessHelper.PhotoType.IMAGE, 'png');
  326. fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
  327. .then(async (file) => {
  328. try {
  329. await fs.write(file.fd, imageBuffer);
  330. ToolsHelper.showMessage('保存成功');
  331. } finally {
  332. await fs.close(file.fd); // 确保文件关闭
  333. }
  334. resolve(uri);
  335. }).catch(() => {
  336. ToolsHelper.showMessage('保存失败');
  337. reject()
  338. return;
  339. });
  340. });
  341. }
  342. /**
  343. * 打开文件,支持使用URI打开文件。使用Promise异步回调。
  344. * @param path string 文件的应用沙箱路径或URI。
  345. * @param mode number 打开文件的选项,必须指定如下选项中的一个,默认以只读方式打开。
  346. * @returns
  347. */
  348. static open(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): Promise<fs.File> {
  349. return fs.open(path, mode);
  350. }
  351. /**
  352. * 打开文件,支持使用URI打开文件。以同步方法。
  353. * @param path string 文件的应用沙箱路径或URI。
  354. * @param mode number 打开文件的选项,必须指定如下选项中的一个,默认以只读方式打开。
  355. * @returns
  356. */
  357. static openSync(path: string, mode: number = fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE): fs.File {
  358. return fs.openSync(path, mode);
  359. }
  360. /**
  361. * 从文件读取数据,使用Promise异步回调。
  362. * @param fd number 已打开的文件描述符。
  363. * @param buffer ArrayBuffer 用于保存读取到的文件数据的缓冲区。
  364. * @param options 支持如下选项:
  365. * offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读。
  366. * length,number类型,表示期望读取数据的长度。可选,默认缓冲区长度。
  367. * @returns
  368. */
  369. static read(fd: number, buffer: ArrayBuffer, options?: ReadOptions): Promise<number> {
  370. return fs.read(fd, buffer, options)
  371. }
  372. /**
  373. * 从文件读取数据,以同步方法。
  374. * @param fd number 已打开的文件描述符。
  375. * @param buffer ArrayBuffer 用于保存读取到的文件数据的缓冲区。
  376. * @param options 支持如下选项:
  377. * offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读。
  378. * length,number类型,表示期望读取数据的长度。可选,默认缓冲区长度。
  379. * @returns
  380. */
  381. static readSync(fd: number, buffer: ArrayBuffer, options?: ReadOptions): number {
  382. return fs.readSync(fd, buffer, options)
  383. }
  384. /**
  385. * 基于文本方式读取文件(即直接读取文件的文本内容),使用Promise异步回调。
  386. * @param filePath 文件的应用沙箱路径。
  387. * @param options 支持如下选项:
  388. * offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读取。
  389. * length,number类型,表示期望读取数据的长度。可选,默认文件长度。
  390. * encoding,string类型,当数据是 string 类型时有效,表示数据的编码方式,默认 'utf-8',仅支持 'utf-8'。
  391. * @returns
  392. */
  393. static readText(filePath: string, options?: ReadTextOptions): Promise<string> {
  394. return fs.readText(filePath, options);
  395. }
  396. /**
  397. * 基于文本方式读取文件(即直接读取文件的文本内容),以同步方法。
  398. * @param filePath 文件的应用沙箱路径。
  399. * @param options 支持如下选项:
  400. * offset,number类型,表示期望读取文件的位置。可选,默认从当前位置开始读取。
  401. * length,number类型,表示期望读取数据的长度。可选,默认文件长度。
  402. * encoding,string类型,当数据是 string 类型时有效,表示数据的编码方式,默认 'utf-8',仅支持 'utf-8'。
  403. * @returns
  404. */
  405. static readTextSync(filePath: string, options?: ReadTextOptions): string {
  406. return fs.readTextSync(filePath, options);
  407. }
  408. /**
  409. * 将数据写入文件,使用Promise异步回调。
  410. * @param fd number 已打开的文件描述符。
  411. * @param buffer ArrayBuffer|string 待写入文件的数据,可来自缓冲区或字符串。
  412. * @param options 支持如下选项:
  413. * offset,number类型,表示期望写入文件的位置。可选,默认从当前位置开始写。
  414. * length,number类型,表示期望写入数据的长度。可选,默认缓冲区长度。
  415. * encoding,string类型,当数据是string类型时有效,表示数据的编码方式,默认 'utf-8'。当前仅支持 'utf-8'。
  416. * @returns
  417. */
  418. static write(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): Promise<number> {
  419. return fs.write(fd, buffer, options)
  420. }
  421. /**
  422. * 将数据写入文件,以同步方法。
  423. * @param fd number 已打开的文件描述符。
  424. * @param buffer ArrayBuffer|string 待写入文件的数据,可来自缓冲区或字符串。
  425. * @param options 支持如下选项:
  426. * offset,number类型,表示期望写入文件的位置。可选,默认从当前位置开始写。
  427. * length,number类型,表示期望写入数据的长度。可选,默认缓冲区长度。
  428. * encoding,string类型,当数据是string类型时有效,表示数据的编码方式,默认 'utf-8'。当前仅支持 'utf-8'。
  429. * @returns
  430. */
  431. static writeSync(fd: number, buffer: ArrayBuffer | string, options?: WriteOptions): number {
  432. return fs.writeSync(fd, buffer, options)
  433. }
  434. /**
  435. * 将数据写入文件,并关闭文件。
  436. * @param path string 文件的应用沙箱路径或URI。
  437. * @param buffer ArrayBuffer|string 待写入文件的数据,可来自缓冲区或字符串。
  438. * @param append 是否追加,true-追加,false-不追加(直接覆盖)
  439. * @returns
  440. */
  441. static async writeEasy(path: string, buffer: ArrayBuffer | string, append: boolean = true): Promise<number> {
  442. try {
  443. let file = FileHelper.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  444. let offset = append ? FileHelper.statSync(file.fd).size : 0
  445. let options: WriteOptions = { offset: offset, encoding: 'utf-8' };
  446. return await FileHelper.write(file.fd, buffer, options).finally(() => {
  447. FileHelper.close(file.fd); //关闭文件
  448. });
  449. } catch (err) {
  450. let error = err as BusinessError;
  451. hilog.error(0x0000, '=====>', `FileHelper-writeEasy-异常 ~ code: ${error.code} -·- message: ${error.message}`)
  452. return -1;
  453. }
  454. }
  455. /**
  456. * 关闭文件,使用Promise异步回调。
  457. * @param file 已打开的File对象或已打开的文件描述符fd。
  458. * @returns
  459. */
  460. static close(file: fs.File | number): Promise<void> {
  461. return fs.close(file);
  462. }
  463. /**
  464. * 关闭文件,以同步方法。
  465. * @param file 已打开的File对象或已打开的文件描述符fd。
  466. */
  467. static closeSync(file: fs.File | number) {
  468. fs.closeSync(file);
  469. }
  470. /**
  471. * 列出文件夹下所有文件名,支持递归列出所有文件名(包含子目录下),支持文件过滤,使用Promise异步回调。
  472. * @param path string 文件夹的应用沙箱路径。
  473. * @param options 文件过滤选项。默认不进行过滤。
  474. * recursion boolean 是否递归子目录下文件名,默认为false。
  475. * listNum number 列出文件名数量。当设置0时,列出所有文件,默认为0。
  476. * filter Filter 文件过滤选项。当前仅支持后缀名匹配、文件名模糊查询、文件大小过滤、最近修改时间过滤。
  477. * @returns
  478. */
  479. static listFile(path: string, options?: ListFileOptions): Promise<string[]> {
  480. return fs.listFile(path, options);
  481. }
  482. /**
  483. * 列出文件夹下所有文件名,支持递归列出所有文件名(包含子目录下),支持文件过滤,以同步方法。
  484. * @param path string 文件夹的应用沙箱路径。
  485. * @param options 文件过滤选项。默认不进行过滤。
  486. * recursion boolean 是否递归子目录下文件名,默认为false。
  487. * listNum number 列出文件名数量。当设置0时,列出所有文件,默认为0。
  488. * filter Filter 文件过滤选项。当前仅支持后缀名匹配、文件名模糊查询、文件大小过滤、最近修改时间过滤。
  489. * @returns
  490. */
  491. static listFileSync(path: string, options?: ListFileOptions): string[] {
  492. return fs.listFileSync(path, options);
  493. }
  494. /**
  495. * 获取文件详细属性信息,使用Promise异步回调。
  496. * @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
  497. */
  498. static stat(file: string | number): Promise<fs.Stat> {
  499. return fs.stat(file);
  500. }
  501. /**
  502. * 获取文件详细属性信息,以同步方法。
  503. * @param file string|number 文件应用沙箱路径path或已打开的文件描述符fd。
  504. * @returns
  505. */
  506. static statSync(file: string | number): fs.Stat {
  507. return fs.statSync(file);
  508. }
  509. /**
  510. * 拷贝文件或者目录,支持拷贝进度监听,使用Promise异步返回。
  511. * @param srcUri 待复制文件或目录的uri。
  512. * @param destUri 目标文件或目录的uri。
  513. * @param options options中提供拷贝进度回调:
  514. * ProgressListener 拷贝进度监听。
  515. * @returns
  516. */
  517. static copy(srcUri: string, destUri: string, options?: fs.CopyOptions): Promise<void> {
  518. return fs.copy(srcUri, destUri, options);
  519. }
  520. /**
  521. * 复制文件,使用Promise异步回调。
  522. * @param src string|number 待复制文件的路径或待复制文件的文件描述符。
  523. * @param dest string|number 目标文件路径或目标文件的文件描述符。
  524. * @param mode number 提供覆盖文件的选项,当前仅支持0,且默认为0。0:完全覆盖目标文件。
  525. * @returns
  526. */
  527. static copyFile(src: string | number, dest: string | number, mode: number = 0): Promise<void> {
  528. return fs.copyFile(src, dest, mode);
  529. }
  530. /**
  531. * 以同步方法复制文件。
  532. * @param src string|number 待复制文件的路径或待复制文件的文件描述符。
  533. * @param dest string|number 目标文件路径或目标文件的文件描述符。
  534. * @param mode number 提供覆盖文件的选项,当前仅支持0,且默认为0。0:完全覆盖目标文件。
  535. */
  536. static copyFileSync(src: string | number, dest: string | number, mode: number = 0) {
  537. fs.copyFileSync(src, dest, mode);
  538. }
  539. /**
  540. * 复制源文件夹至目标路径下,只能复制沙箱里的文件夹,使用Promise异步返回。
  541. * @param src 源文件夹的应用沙箱路径。
  542. * @param dest 目标文件夹的应用沙箱路径。
  543. * @param mode 复制模式:
  544. * mode为0,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
  545. * mode为1,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
  546. * @returns
  547. */
  548. static copyDir(src: string, dest: string, mode: number = 1): Promise<void> {
  549. return fs.copyDir(src, dest, mode);
  550. }
  551. /**
  552. * 以同步方法复制源文件夹至目标路径下,只能复制沙箱里的文件夹。
  553. * @param src 源文件夹的应用沙箱路径。
  554. * @param dest 目标文件夹的应用沙箱路径。
  555. * @param mode 复制模式:
  556. * mode为0,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
  557. * mode为1,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
  558. * @returns
  559. */
  560. static copyDirSync(src: string, dest: string, mode: number = 1) {
  561. fs.copyDirSync(src, dest, mode);
  562. }
  563. /**
  564. * 移动文件,使用Promise异步回调。
  565. * @param src string 源文件的应用沙箱路径。
  566. * @param dest string 目的文件的应用沙箱路径。
  567. * @param mode number 移动模式。若mode为0,移动位置存在同名文件时,强制移动覆盖。若mode为1,移动位置存在同名文件时,抛出异常。默认为0。
  568. * @returns
  569. */
  570. static moveFile(src: string, dest: string, mode: number = 0): Promise<void> {
  571. return fs.moveFile(src, dest, mode)
  572. }
  573. /**
  574. * 移动文件,以同步方法。
  575. * @param src string 源文件的应用沙箱路径。
  576. * @param dest string 目的文件的应用沙箱路径。
  577. * @param mode number 移动模式。若mode为0,移动位置存在同名文件时,强制移动覆盖。若mode为1,移动位置存在同名文件时,抛出异常。默认为0。
  578. * @returns
  579. */
  580. static moveFileSync(src: string, dest: string, mode: number = 0) {
  581. fs.moveFileSync(src, dest, mode)
  582. }
  583. /**
  584. * 移动源文件夹至目标路径下,使用Promise异步返回。
  585. * @param src 源文件夹的应用沙箱路径
  586. * @param dest 目标文件夹的应用沙箱路径
  587. * @param mode 移动模式:
  588. * mode为0,文件夹级别抛异常。若目标文件夹下存在与源文件夹名冲突的非空文件夹,则抛出异常。
  589. * mode为1,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
  590. * mode为2,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
  591. * mode为3,文件夹级别强制覆盖。移动源文件夹至目标文件夹下,目标文件夹下移动的文件夹内容与源文件夹完全一致。若目标文件夹下存在与源文件夹名冲突的文件夹,该文件夹下所有原始文件将不会保留。
  592. * @returns
  593. */
  594. static moveDir(src: string, dest: string, mode: number = 3): Promise<void> {
  595. return fs.moveDir(src, dest, mode);
  596. }
  597. /**
  598. * 以同步方法移动源文件夹至目标路径下。
  599. * @param src 源文件夹的应用沙箱路径
  600. * @param dest 目标文件夹的应用沙箱路径
  601. * @param mode 移动模式:
  602. * mode为0,文件夹级别抛异常。若目标文件夹下存在与源文件夹名冲突的非空文件夹,则抛出异常。
  603. * mode为1,文件级别抛异常。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则抛出异常。源文件夹下未冲突的文件全部移动至目标文件夹下,目标文件夹下未冲突文件将继续保留,且冲突文件信息将在抛出异常的data属性中以Array<ConflictFiles>形式提供。
  604. * mode为2,文件级别强制覆盖。目标文件夹下存在与源文件夹名冲突的文件夹,若冲突文件夹下存在同名文件,则强制覆盖冲突文件夹下所有同名文件,未冲突文件将继续保留。
  605. * mode为3,文件夹级别强制覆盖。移动源文件夹至目标文件夹下,目标文件夹下移动的文件夹内容与源文件夹完全一致。若目标文件夹下存在与源文件夹名冲突的文件夹,该文件夹下所有原始文件将不会保留。
  606. * @returns
  607. */
  608. static moveDirSync(src: string, dest: string, mode: number = 3) {
  609. return fs.moveDirSync(src, dest, mode);
  610. }
  611. /**
  612. * 截断文件,使用Promise异步回调。
  613. * @param file string|number 文件的应用沙箱路径或已打开的文件描述符fd。
  614. * @param len number 文件截断后的长度,以字节为单位。默认为0。
  615. * @returns
  616. */
  617. static truncate(file: string | number, len: number = 0): Promise<void> {
  618. return fs.truncate(file, len)
  619. }
  620. /**
  621. * 截断文件,以同步方法。
  622. * @param file string|number 文件的应用沙箱路径或已打开的文件描述符fd。
  623. * @param len number 文件截断后的长度,以字节为单位。默认为0。
  624. * @returns
  625. */
  626. static truncateSync(file: string | number, len: number = 0) {
  627. fs.truncateSync(file, len)
  628. }
  629. /**
  630. * 获取链接文件信息,使用Promise异步回调。
  631. * @param path string 文件的应用沙箱路径。
  632. * @returns
  633. */
  634. static lstat(path: string): Promise<fs.Stat> {
  635. return fs.lstat(path);
  636. }
  637. /**
  638. * 获取链接文件信息,以同步方法。
  639. * @param path string 文件的应用沙箱路径。
  640. * @returns
  641. */
  642. static lstatSync(path: string): fs.Stat {
  643. return fs.lstatSync(path);
  644. }
  645. /**
  646. * 同步文件数据,使用Promise异步回调。
  647. * @param fd number 已打开的文件描述符。
  648. * @returns
  649. */
  650. static fsync(fd: number): Promise<void> {
  651. return fs.fsync(fd);
  652. }
  653. /**
  654. * 同步文件数据,以同步方法。
  655. * @param fd number 已打开的文件描述符。
  656. */
  657. static fsyncSync(fd: number) {
  658. fs.fsyncSync(fd);
  659. }
  660. /**
  661. * 实现文件内容数据同步,使用Promise异步回调。
  662. * @param fd number 已打开的文件描述符。
  663. * @returns
  664. */
  665. static fdatasync(fd: number): Promise<void> {
  666. return fs.fdatasync(fd);
  667. }
  668. /**
  669. * 实现文件内容数据同步,以同步方法。
  670. * @param fd number 已打开的文件描述符。
  671. */
  672. static fdatasyncSync(fd: number) {
  673. fs.fdatasyncSync(fd);
  674. }
  675. /**
  676. * 基于文件路径打开文件流,使用Promise异步回调。
  677. * @param path string 文件的应用沙箱路径。
  678. * @param mode string 文件打开类型
  679. * r:打开只读文件,该文件必须存在。
  680. * r+:打开可读写的文件,该文件必须存在。
  681. * w:打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  682. * w+:打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  683. * a:以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
  684. * a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
  685. * @returns
  686. */
  687. static createStream(path: string, mode: string = 'r'): Promise<fs.Stream> {
  688. return fs.createStream(path, mode)
  689. }
  690. /**
  691. * 基于文件路径打开文件流,以同步方法。
  692. * @param path string 文件的应用沙箱路径。
  693. * @param mode string 文件打开类型
  694. * r:打开只读文件,该文件必须存在。
  695. * r+:打开可读写的文件,该文件必须存在。
  696. * w:打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  697. * w+:打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  698. * a:以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
  699. * a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
  700. * @returns
  701. */
  702. static createStreamSync(path: string, mode: string = 'r'): fs.Stream {
  703. return fs.createStreamSync(path, mode);
  704. }
  705. /**
  706. * 基于文件描述符打开文件流,使用Promise异步回调。
  707. * @param fd number 已打开的文件描述符。
  708. * @param mode string 文件打开类型
  709. * r:打开只读文件,该文件必须存在。
  710. * r+:打开可读写的文件,该文件必须存在。
  711. * w:打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  712. * w+:打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  713. * a:以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
  714. * a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
  715. * @returns
  716. */
  717. static fdopenStream(fd: number, mode: string = 'r'): Promise<fs.Stream> {
  718. return fs.fdopenStream(fd, mode)
  719. }
  720. /**
  721. * 基于文件描述符打开文件流,以同步方法。
  722. * @param fd number 已打开的文件描述符。
  723. * @param mode string 文件打开类型
  724. * r:打开只读文件,该文件必须存在。
  725. * r+:打开可读写的文件,该文件必须存在。
  726. * w:打开只写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  727. * w+:打开可读写文件,若文件存在则文件长度清0,即该文件内容会消失。若文件不存在则建立该文件。
  728. * a:以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
  729. * a+:以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
  730. * @returns
  731. */
  732. static fdopenStreamSync(fd: number, mode: string = 'r'): fs.Stream {
  733. return fs.fdopenStreamSync(fd, mode)
  734. }
  735. /**
  736. * 创建临时目录,使用Promise异步回调。
  737. * @param prefix string 用随机产生的字符串替换以“XXXXXX”结尾目录路径。
  738. * @returns
  739. */
  740. static mkdtemp(prefix: string): Promise<string> {
  741. return fs.mkdtemp(prefix);
  742. }
  743. /**
  744. * 创建临时目录,以同步的方法。
  745. * @param prefix string 用随机产生的字符串替换以“XXXXXX”结尾目录路径。
  746. * @returns
  747. */
  748. static mkdtempSync(prefix: string): string {
  749. return fs.mkdtempSync(prefix);
  750. }
  751. /**
  752. * 将文件描述符转化为File。
  753. * @param fd 文件描述符。
  754. * @returns
  755. */
  756. static dup(fd: number): fs.File {
  757. return fs.dup(fd);
  758. }
  759. /**
  760. * 修改文件最近访问时间属性。
  761. * path 文件的应用沙箱路径。
  762. * mtime 待更新的时间戳。自1970年1月1日起至目标时间的毫秒数。仅支持修改文件最近访问时间属性。
  763. * @returns
  764. */
  765. static utimes(path: string, mtime: number): void {
  766. fs.utimes(path, mtime);
  767. }
  768. /**
  769. * 格式化文件大小
  770. * @param fileSize
  771. * @returns
  772. */
  773. static getFormatFileSize(fileSize: number): string {
  774. if (fileSize < 1024) {
  775. return fileSize + "B";
  776. } else if (fileSize < 1024 * 1024) {
  777. return (fileSize / 1024).toFixed(1) + "KB";
  778. } else if (fileSize < 1024 * 1024 * 1024) {
  779. return (fileSize / (1024 * 1024)).toFixed(1) + "MB";
  780. } else if (fileSize < 1024 * 1024 * 1024 * 1024) {
  781. return (fileSize / (1024 * 1024 * 1024)).toFixed(1) + "GB";
  782. } else {
  783. return (fileSize / (1024 * 1024 * 1024 * 1024)).toFixed(1) + "TB";
  784. }
  785. }
  786. static copyFileToCacheDir(path: string):CacheFile {
  787. const resFile = fileIo.openSync(path, fileIo.OpenMode.READ_ONLY)
  788. let newPath = GlobalContext.getContext().cacheDir + "/" + resFile.name;
  789. FileHelper.copyFileSync(resFile.fd, newPath)
  790. return {
  791. path: newPath,
  792. name: resFile.name
  793. }
  794. }
  795. }
  796. export interface CacheFile{
  797. path:string,
  798. name:string
  799. }