鸿蒙学习实战之路-应用及文件系统空间统计完全指南

最近好多朋友问我:“西兰花啊,我开发的应用总是提示存储空间不足,但不知道怎么查看具体的空间使用情况,咋办呢?” 害,这问题可问对人了!

今天这篇,我就手把手带你掌握鸿蒙应用的空间监控技能,就像厨房里要时刻关注冰箱容量一样重要!全程不超过 5 分钟(不含下载时间)~


🥦 痛点场景:你是否也遇到过这些情况?

  • 应用运行到一半突然提示"存储空间不足"
  • 想优化应用体积,但不知道具体占用在哪里
  • 缓存目录总是爆满,不知道如何清理
  • 想要监控应用的空间使用趋势

别慌!这些问题的根源都是缺少有效的空间监控机制。

🎯 学完这篇你能收获什么?

  • 掌握鸿蒙应用空间统计的核心API
  • 学会获取文件系统剩余空间
  • 了解应用各部分空间占用情况
  • 实现实时空间监控功能

第一步:认识空间统计的核心API

在鸿蒙中,空间统计主要靠这两个模块:

// 文件系统空间统计
import { statfs } from '@kit.CoreFileKit';

// 应用空间统计  
import { storageStatistics } from '@kit.CoreFileKit';

这就像厨房里的两个秤:一个称总容量(文件系统),一个称具体食材重量(应用空间)。

🥦 西兰花小贴士

这两个模块的区别就像"整个冰箱有多大"和"我的食材占多少地方",一个管整体,一个管局部!


第二步:获取文件系统剩余空间

2.1 异步方式获取剩余空间

import { statfs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';

// 获取应用上下文
const context = this.getUIContext().getHostContext() as common.UIAbilityContext;
const 应用文件路径 = context.filesDir;

// 异步获取剩余空间大小
statfs.getFreeSize(应用文件路径, (错误: BusinessError, 剩余字节数: number) => {
  if (错误) {
    console.error(`获取剩余空间失败,错误代码: ${错误.code}, 错误信息: ${错误.message}`);
  } else {
    console.info(`剩余空间: ${剩余字节数} 字节 (${(剩余字节数 / 1024 / 1024 / 1024).toFixed(2)} GB)`);
  }
});

2.2 同步方式获取剩余空间

import { statfs } from '@kit.CoreFileKit';

try {
  const 剩余空间 = statfs.getFreeSizeSync(应用文件路径);
  console.info(`剩余空间: ${剩余空间} 字节`);
} catch (错误) {
  console.error(`获取剩余空间失败: ${错误.message}`);
}

第三步:监控应用整体空间占用

3.1 获取应用存储空间大小

import { storageStatistics } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';

storageStatistics.getCurrentBundleStats((错误: BusinessError, 应用统计: storageStatistics.BundleStats) => {
  if (错误) {
    console.error(`获取应用统计失败,错误代码: ${错误.code}, 错误信息: ${错误.message}`);
  } else {
    console.log(`应用空间统计:`);
    console.log(`📱 应用安装文件大小: ${应用统计.appSize} 字节 (${(应用统计.appSize / 1024 / 1024).toFixed(2)} MB)`);
    console.log(`💾 缓存文件大小: ${应用统计.cacheSize} 字节 (${(应用统计.cacheSize / 1024 / 1024).toFixed(2)} MB)`);
    console.log(`📁 应用文件大小: ${应用统计.dataSize} 字节 (${(应用统计.dataSize / 1024 / 1024).toFixed(2)} MB)`);
    
    const 总大小 = 应用统计.appSize + 应用统计.cacheSize + 应用统计.dataSize;
    console.log(`📊 总计: ${总大小} 字节 (${(总大小 / 1024 / 1024).toFixed(2)} MB)`);
  }
});

3.2 异步获取内置存储总空间

storageStatistics.getTotalSize()
  .then((总字节数: number) => {
    console.info(`内置存储总空间: ${总字节数} 字节 (${(总字节数 / 1024 / 1024 / 1024).toFixed(2)} GB)`);
  })
  .catch((错误: BusinessError) => {
    console.error(`获取总空间失败,错误代码: ${错误.code}, 错误信息: ${错误.message}`);
  });

3.3 同步获取内置存储总空间

import { storageStatistics } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';

try {
  const 总空间 = storageStatistics.getTotalSizeSync();
  console.info(`内置存储总空间: ${总空间} 字节 (${(总空间 / 1024 / 1024 / 1024).toFixed(2)} GB)`);
} catch (错误) {
  const 业务错误: BusinessError = 错误 as BusinessError;
  console.error(`同步获取总空间失败,错误代码: ${业务错误.code}, 错误信息: ${业务错误.message}`);
}

3.4 异步获取内置存储可用空间

storageStatistics.getFreeSize()
  .then((可用字节数: number) => {
    console.info(`内置存储可用空间: ${可用字节数} 字节 (${(可用字节数 / 1024 / 1024 / 1024).toFixed(2)} GB)`);
  })
  .catch((错误: BusinessError) => {
    console.error(`获取可用空间失败,错误代码: ${错误.code}, 错误信息: ${错误.message}`);
  });

3.5 同步获取内置存储可用空间

try {
  const 可用空间 = storageStatistics.getFreeSizeSync();
  console.info(`内置存储可用空间: ${可用空间} 字节 (${(可用空间 / 1024 / 1024 / 1024).toFixed(2)} GB)`);
} catch (错误) {
  const 业务错误: BusinessError = 错误 as BusinessError;
  console.error(`同步获取可用空间失败,错误代码: ${业务错误.code}, 错误信息: ${业务错误.message}`);
}

第四步:创建一个完整的空间监控组件

import { statfs, storageStatistics } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';

@Entry
@ComponentV2
struct 空间监控器 {
  @Local 监控信息: string = '点击下方按钮开始监控空间使用情况';
  @Local 总空间: string = '';
  @Local 可用空间: string = '';
  @Local 应用空间: string = '';

  build() {
    Column({ space: 20 }) {
      Text('🥦 西兰花空间监控台')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor('#2E7D32')

      Button('开始空间监控')
        .onClick(() => {
          this.执行空间监控();
        })
        .backgroundColor('#4CAF50')
        .fontColor(Color.White)
        .fontSize(16)
        .borderRadius(8)

      Text(this.监控信息)
        .fontSize(14)
        .fontColor('#666666')
        .padding(20)
        .backgroundColor('#F5F5F5')
        .borderRadius(10)
        .width('100%')

      if (this.总空间 && this.可用空间 && this.应用空间) {
        Column({ space: 10 }) {
          Text('📊 空间统计详情')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .fontColor('#1976D2')

          Text(`📦 内置存储总空间: ${this.总空间}`)
            .fontSize(14)
            .fontColor('#333333')

          Text(`💾 可用空间: ${this.可用空间}`)
            .fontSize(14)
            .fontColor('#333333')

          Text(`📱 应用占用空间: ${this.应用空间}`)
            .fontSize(14)
            .fontColor('#333333')
        }
        .width('100%')
        .padding(15)
        .backgroundColor('#E3F2FD')
        .borderRadius(8)
      }
    }
    .padding(20)
  }

  async 执行空间监控() {
    this.监控信息 = '正在监控空间使用情况...';

    try {
      // 获取上下文
      const context = this.getUIContext().getHostContext() as common.UIAbilityContext;
      const 应用路径 = context.filesDir;

      // 并行执行所有监控任务
      const [文件系统可用空间, 内置存储总空间, 内置存储可用空间, 应用统计] = await Promise.all([
        // 文件系统可用空间
        new Promise<number>((resolve, reject) => {
          statfs.getFreeSize(应用路径, (错误: BusinessError, 空间大小: number) => {
            if (错误) {
              reject(错误);
            } else {
              resolve(空间大小);
            }
          });
        }),

        // 内置存储总空间
        storageStatistics.getTotalSize(),

        // 内置存储可用空间
        storageStatistics.getFreeSize(),

        // 应用空间统计
        new Promise<storageStatistics.BundleStats>((resolve, reject) => {
          storageStatistics.getCurrentBundleStats((错误: BusinessError, 统计: storageStatistics.BundleStats) => {
            if (错误) {
              reject(错误);
            } else {
              resolve(统计);
            }
          });
        })
      ]);

      // 格式化空间大小
      const 格式化空间大小 = (字节数: number): string => {
        if (字节数 >= 1024 * 1024 * 1024) {
          return `${(字节数 / 1024 / 1024 / 1024).toFixed(2)} GB`;
        } else if (字节数 >= 1024 * 1024) {
          return `${(字节数 / 1024 / 1024).toFixed(2)} MB`;
        } else if (字节数 >= 1024) {
          return `${(字节数 / 1024).toFixed(2)} KB`;
        } else {
          return `${字节数} 字节`;
        }
      };

      this.总空间 = 格式化空间大小(内置存储总空间);
      this.可用空间 = 格式化空间大小(内置存储可用空间);
      
      const 应用总大小 = 应用统计.appSize + 应用统计.cacheSize + 应用统计.dataSize;
      this.应用空间 = 格式化空间大小(应用总大小);

      this.监控信息 = `✅ 空间监控完成!
📈 文件系统可用空间: ${格式化空间大小(文件系统可用空间)}
💾 存储空间使用率: ${((1 - 内置存储可用空间 / 内置存储总空间) * 100).toFixed(1)}%`;

      console.log('空间监控执行完成');
    } catch (错误) {
      this.监控信息 = `❌ 监控失败: ${错误.message}`;
      console.error(`空间监控失败: ${错误}`);
    }
  }
}

🥦 西兰花警告

空间监控涉及到系统权限,在真实开发中需要注意:

  1. 权限申请:确保应用有足够的文件系统访问权限
  2. 性能考虑:空间监控不宜过于频繁,建议间隔1分钟以上
  3. 错误处理:始终包含完整的错误处理逻辑,避免应用崩溃
  4. 用户隐私:不要存储或传输用户的空间使用数据

🥦 西兰花小贴士

空间优化小技巧:

  1. 定期清理:建议应用启动时检查缓存大小,超过阈值时自动清理
  2. 分级存储:重要数据放EL1目录,临时数据放cache目录
  3. 压缩存储:对于大文件,考虑使用压缩算法
  4. 云端同步:将不常用的数据同步到云端,释放本地空间

📚 推荐资料

想要深入学习空间管理?这些官方文档是你的好朋友:


我是盐焗西兰花,
不教理论,只给你能跑的代码和避坑指南。
下期见!🥦

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐