
《HarmonyOS技术精讲-Core File Kit》第11篇文件元数据读取——大小、时间与类型获取文件元数据比你想的要复杂HarmonyOS NEXT 开发里fileManager.stat这个 API 经常被误用。很多人拿到文件路径后第一反应是打开文件流去读文件头或者逐字节统计大小或者直接用new Date()去猜文件时间——这些做法在性能上都不合适。实际开发中文件元数据的读取需求很常见显示文件详情、排序文件列表、判断文件类型做分类展示。Core File Kit 提供的stat方法可以直接获取这些信息不需要打开文件流也不需要在应用层做额外计算。这个功能本身不复杂但真正容易出问题的点是返回的 FileStat 对象各个属性的含义和类型判断的边界情况。解决什么问题stat是一个系统级调用直接从文件系统 inode 节点读取元数据。相比打开文件流再读取方式性能获取信息量适用场景fileManager.stat高不打开文件大小、时间、类型、权限等文件列表、详情展示打开文件流读取低需要 I/O 操作主要获取内容文件内容处理fs.access高仅判断存在性检查文件是否存在推荐直接使用stat这也是 Core File Kit 提供这个能力的初衷。环境说明DevEco Studio 版本DevEco Studio 6.1.0 及以上 HarmonyOS SDK 版本HarmonyOS 6.1.0(23) 及以上 目标设备手机 / 平板核心实现读取文件大小、时间与类型下面这段代码实现了一个完整的文件信息读取功能。它接收一个文件路径返回文件大小、最后修改时间、创建时间以及根据扩展名判断的文件类型。import{fileManager}fromkit.CoreFileKit;import{common}fromkit.AbilityKit;interfaceFileMetaData{size:number;// 文件大小单位字节sizeDesc:string;// 可读的大小描述如 1.2 MBmtime:Date;// 最后修改时间ctime:Date;// 创建时间fileType:string;// 文件类型描述如 图片、文档extension:string;// 文件扩展名mimeType:string;// MIME 类型}classFileMetaReader{privatecontext:common.Context;constructor(context:common.Context){this.contextcontext;}asyncgetFileMeta(filePath:string):PromiseFileMetaData{// 1. 调用 stat 获取文件元数据conststatawaitfileManager.stat(filePath);// 2. 计算可读的文件大小constsizeDescthis.formatSize(stat.size);// 3. 获取扩展名并判断文件类型constextensionthis.getExtension(filePath);constmimeTypethis.getMimeType(extension);constfileTypethis.getFileTypeDesc(extension);return{size:stat.size,sizeDesc,mtime:newDate(stat.mtime),ctime:newDate(stat.ctime),fileType,extension,mimeType};}privateformatSize(bytes:number):string{if(bytes0)return0 B;constunits[B,KB,MB,GB,TB];constk1024;constiMath.floor(Math.log(bytes)/Math.log(k));returnparseFloat((bytes/Math.pow(k,i)).toFixed(2)) units[i];}privategetExtension(path:string):string{constdotIndexpath.lastIndexOf(.);if(dotIndex-1)return;returnpath.substring(dotIndex1).toLowerCase();}privategetMimeType(ext:string):string{constmimeMap:Recordstring,string{jpg:image/jpeg,jpeg:image/jpeg,png:image/png,gif:image/gif,webp:image/webp,mp4:video/mp4,mp3:audio/mpeg,pdf:application/pdf,txt:text/plain,json:application/json,html:text/html,js:application/javascript,css:text/css};returnmimeMap[ext]||application/octet-stream;}privategetFileTypeDesc(ext:string):string{consttypeMap:Recordstring,string{图片:[jpg,jpeg,png,gif,webp,bmp,svg],视频:[mp4,avi,mov,mkv,flv,wmv],音频:[mp3,wav,flac,aac,ogg],文档:[pdf,doc,docx,xls,xlsx,ppt,pptx,txt],压缩包:[zip,rar,7z,tar,gz],代码:[js,ts,html,css,json,xml,py,java]};for(const[type,exts]ofObject.entries(typeMap)){if(exts.includes(ext)){returntype;}}return未知;}}关键点说明fileManager.stat返回的FileStat对象中size是字节数mtime和ctime是时间戳毫秒需要自行转为Date对象。文件类型判断这里用了扩展名映射实际项目中如果要求更高可以读取文件头字节来判断但性能会差一些。formatSize方法处理了可读大小格式化注意单位用 1024 而不是 1000。使用示例EntryComponentstruct FileInfoDemo{StatefileInfo:string;build(){Column(){Button(读取文件信息).onClick(async(){constreadernewFileMetaReader(getContext(this));constsandboxPathgetContext(this).getApplicationContext().cacheDir;consttestFilePathsandboxPath/test.txt;// 先创建一个测试文件constfileawaitfileManager.open(testFilePath,fileManager.OpenMode.CREATE);awaitfileManager.write(file.fd,Hello HarmonyOS);awaitfileManager.close(file);constmetaawaitreader.getFileMeta(testFilePath);this.fileInfo大小:${meta.sizeDesc}\n修改时间:${meta.mtime.toLocaleString()}\n类型:${meta.fileType};});Text(this.fileInfo).padding(16).fontSize(14);}.padding(24);}}常见问题问题 1stat返回的时间是 UTC 还是本地时间现象获取到的mtime和ctime打印出来发现和系统时间对不上。原因FileStat.mtime和FileStat.ctime返回的是从 1970-01-01 00:00:00 UTC 到事件发生时的毫秒数相当于 Unix 时间戳。这个值本身是 UTC 基准不包含时区信息。解决方案使用new Date(stat.mtime)创建 Date 对象时Date 会自动转为本地时区。如果要显示给用户直接用toLocaleString()即可不需要手动加减时区偏移。问题 2扩展名不存在的文件怎么处理类型判断现象部分系统文件或临时文件没有扩展名getExtension返回空字符串导致 MIME 类型回退为application/octet-stream。原因扩展名判断是轻量方案但无法覆盖无扩展名或自定义扩展名的文件。解决方案对于无扩展名的文件可以结合FileStat.mode判断文件类型如目录、普通文件、符号链接等或者读取文件的前 4-8 个字节做魔数判断。mode的值是文件权限和类型的组合可以通过位掩码解析。最佳实践不要在主线程频繁调用stat虽然stat是轻量级调用但在文件列表场景下如果一次性调用几百次仍然会造成 UI 卡顿。建议在子线程或使用TaskPool批量处理。mtime和ctime不要混用mtime是最后修改时间ctime是状态更改时间包括权限、重命名等。做文件排序时一般用mtime做备份同步时建议用ctime。MIME 类型判断推荐用扩展名白名单服务端上传文件时经常需要校验 MIME 类型。客户端判断可以用扩展名映射但务必配合白名单机制防止伪造扩展名绕过限制。如果安全性要求高需要读取文件头验证。FAQQstat返回的size是实际占用磁盘空间吗A不是。size是文件逻辑大小即文件内容的实际字节数。磁盘占用空间通常更大因为文件系统块对齐这个值需要通过stat.blocks计算。Q为什么同个文件多次调用stat返回的mtime不一样Amtime的单位是毫秒但文件系统的精度可能只有秒级或纳秒级。如果文件没有被修改mtime应该是相同的。如果观察到差异检查代码中是否有无意中修改文件属性的操作。Q应用沙箱外的文件能用stat吗A受限于 HarmonyOS 的沙箱机制stat只能访问应用自身沙箱内的文件以及通过fileManager.open或文件选择器授权后的文件。跨应用访问需要对应权限声明。示例代码地址项目地址