App Inventor 2 文件操作教程 - 创建/读取/写入/管理文件

« 返回首页

概述

App Inventor 2提供了 File 组件进行文件操作。本文介绍:

  • 文件路径概念
  • 创建文件和目录
  • 读取和写入文件
  • 文件管理(复制、删除)
  • FileTools扩展的高级功能

File组件核心方法

方法 说明
SaveFile(text, fileName) 保存文本到文件
AppendToFile(text, fileName) 追加文本到文件
ReadFrom(fileName) 读取文件内容
Delete(fileName) 删除文件

核心事件

事件 参数 说明
GotText(text) 文件内容 读取完成时触发
Saved(fileName) 文件名 保存完成时触发

文件路径

路径格式

App Inventor中的文件路径以 / 开头:

路径 说明
/fileName 应用私有目录(默认)
/sdcard/fileName 外部存储根目录
/sdcard/DCIM/ 相册目录
/sdcard/Download/ 下载目录
/sdcard/AppInventor/ App Inventor默认目录

创建指定文件路径

when 按钮_创建文件.Click() {
  var 文件路径 = "/sdcard/MyApp/data.txt"
  文件管理器1.SaveFile("初始内容", 文件路径)
}
when 文件管理器1.SaveFile(文件名) {
  标签_状态.Text = join("✅ 文件已创建:", 文件名)
}

注意:Android 10+的分区存储限制,应用默认只能访问自己的私有目录。访问 /sdcard/ 其他目录需要 WRITE_EXTERNAL_STORAGE 权限。

创建目录

App Inventor的File组件不能直接创建目录,但可以通过以下方式间接实现:

方法1:保存文件时自动创建路径

// 保存文件到子目录,目录会自动创建
文件管理器1.SaveFile("数据", "/sdcard/MyApp/subfolder/file.txt")

方法2:使用FileTools扩展

文件管理器_Tools1.MakeDirectory("/sdcard/MyApp/new_folder")

写入文件

写入文本

when 按钮_保存.Click() {
  var 内容 = 文本输入框_内容.Text
  文件管理器1.SaveFile(内容, "/sdcard/MyApp/notes.txt")
}

追加内容

when 按钮_追加.Click() {
  var 时间戳 = 计时器1.FormatDateTime(计时器1.Now(), "yyyy-MM-dd HH:mm:ss")
  var 追加内容 = join(时间戳, ": ", 文本输入框_内容.Text, "\n")
  文件管理器1.AppendToFile(追加内容, "/sdcard/MyApp/log.txt")
}

写入JSON数据

当 按钮_保存数据.被点击
  设 数据字典 = 创建字典(
    "name" → 文本输入框_姓名.文本,
    "score" → 输入框_分数.文本,
    "date" → 计时器1.格式化日期时间(计时器1.当前时间(), "yyyy-MM-dd")
  )
  设 JSON文本 = 调用 文本.转JSON(数据字典)
  调用 文件管理器1.保存文件(JSON文本, "/sdcard/MyApp/data.json")

读取文件

基本读取

when 按钮_读取.Click() {
  文件管理器1.ReadFrom("/sdcard/MyApp/notes.txt")
}
when 文件管理器1.GotText(内容) {
  标签_内容.Text = 内容
}

读取并解析JSON

当 文件管理器1.收到文本(内容)
  设 数据 = 调用 文本.从JSON解析(内容)
  设 姓名 = 从字典 数据 获取 "name"
  设 分数 = 从字典 数据 获取 "score"
  标签_显示.文本 = 姓名 & ":" & 分数 & "分"

逐行处理

when 文件管理器1.GotText(内容) {
  var 行列表 = split(内容, "\n")
  var i = 1
  while i <= length(行列表) {
    var 当前行 = 行列表[i]
    // 处理每一行...
    var i = i + 1
  }
}

CSV文件操作

写入CSV

当 按钮_导出CSV.被点击
  设 CSV内容 = "姓名,年龄,城市\n"
  设 i = 1
  当 i ≤ 列表长度(数据列表)
    设 记录 = 列表第i项(数据列表)
    设 CSV内容 = CSV内容 & 
      从字典 记录 获取 "name" & "," &
      从字典 记录 获取 "age" & "," &
      从字典 记录 获取 "city" & "\n"
    设 i = i + 1
  调用 文件管理器1.保存文件(CSV内容, "/sdcard/MyApp/export.csv")

读取CSV

当 文件管理器1.收到文本(内容)
  设 行列表 = 分割文本(内容, "\n")
  设 数据列表 = 创建空列表
  设 i = 2  ' 跳过标题行
  当 i ≤ 列表长度(行列表)
    设 字段 = 分割文本(列表第i项(行列表), ",")
    如果 列表长度(字段) ≥ 3
      设 记录 = 创建字典(
        "name" → 列表第1项(字段),
        "age" → 列表第2项(字段),
        "city" → 列表第3项(字段)
      )
      设 数据列表 = 添加列表项(数据列表, 记录)
    设 i = i + 1

FileTools扩展

FileTools 扩展提供了更强大的文件操作能力。

核心功能

功能 方法
复制文件 CopyFile(source, dest)
移动文件 MoveFile(source, dest)
列出目录 ListFiles(directory)
创建目录 MakeDir(path)
删除目录 DeleteDir(path)
文件是否存在 Exists(path)
保存到相册 SaveFileToGallery(path)
扫描媒体文件 ScanFile(path)

使用示例

// 复制文件到相册
when 按钮_保存到相册.Click() {
  文件管理器_Tools1.CopyFile(图片路径, join("/sdcard/DCIM/Camera/photo_", 时间戳, ".png"))
  文件管理器_Tools1.扫描文件(join("/sdcard/DCIM/Camera/photo_", 时间戳, ".png"))
  // 列出目录文件
}
when 按钮_列出文件.Click() {
  文件管理器_Tools1.ListDirectory("/sdcard/MyApp/")
}
when 文件管理器_Tools1.ListFiles(文件列表) {
  var 显示 = ""
  var i = 1
  while i <= length(文件列表) {
    var 显示 = join(显示, 文件列表[i], "\n")
    var i = i + 1
  }
  var 标签_文件文本 = 显示
}

存储照片

从Camera保存到指定路径

when 按钮_拍照.Click() {
  照相机1.TakePicture()
}
when 照相机1.AfterPicture(图片路径) {
  // 复制到自己的目录
  var 新路径 = join("/sdcard/MyApp/photos/", 计时器1.FormatDateTime(计时器1.Now(), "yyyyMMdd_HHmmss"), ".jpg")
  文件管理器_Tools1.CopyFile(图片路径, 新路径)
  标签_状态.Text = join("✅ 照片已保存:", 新路径)
}

存储到相册(通知系统刷新)

when 按钮_存相册.Click() {
  文件管理器_Tools1.SaveFile(图片路径)
  // FileTools会自动通知系统扫描
}

已知问题:部分设备保存到相册后需要重启手机才可见。使用 ScanFile 方法可以触发系统媒体扫描。

常见问题

Q1: 保存文件时提示权限拒绝?

Android 6.0+需要动态申请存储权限。在Screen1的Properties中设置:

  • ReadWriteExternalStorage = true

Q2: 如何判断文件是否存在?

使用FileTools扩展的 Exists 方法,或者尝试读取文件:

文件管理器1.ReadFrom(目标路径)
when 文件管理器1.GotText(内容) {
  if 内容 == "" {
    标签_状态.Text = "文件不存在或为空"
  } else {
    标签_状态.Text = "文件存在"
  }
}

Q3: 如何处理大文件?

  • 读取大文件(>1MB)可能导致App卡顿
  • 使用分块读取或只读取需要的部分
  • 图片文件直接用Image组件加载路径,不需要用File读取

Q4: FileTools扩展保存到相册需要重启?

这是Android媒体扫描机制的已知问题。解决方案:

  1. 调用 ScanFile 主动触发扫描
  2. 使用 MediaStore API(需要扩展支持)
  3. 接受这个限制,告知用户稍等片刻

总结

需求 组件/方法 推荐
简单读写 File组件
复制/移动/目录 FileTools扩展
保存到相册 FileTools
CSV导出 File + 文本处理
JSON数据 File + 字典
大文件处理 WebView + JS 高级

版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。

文档反馈