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默认目录

创建指定文件路径

当 按钮_创建文件.被点击
  设 文件路径 = "/sdcard/MyApp/data.txt"
  调用 File1.保存文件("初始内容", 文件路径)

当 File1.保存完成(文件名)
  标签_状态.文本 = "✅ 文件已创建:" & 文件名

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

创建目录

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

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

' 保存文件到子目录,目录会自动创建
调用 File1.保存文件("数据", "/sdcard/MyApp/subfolder/file.txt")

方法2:使用FileTools扩展

调用 FileTools1.创建目录("/sdcard/MyApp/new_folder")

写入文件

写入文本

当 按钮_保存.被点击
  设 内容 = 输入框_内容.文本
  调用 File1.保存文件(内容, "/sdcard/MyApp/notes.txt")

追加内容

当 按钮_追加.被点击
  设 时间戳 = Clock1.格式化日期时间(Clock1.当前时间(), "yyyy-MM-dd HH:mm:ss")
  设 追加内容 = 时间戳 & ": " & 输入框_内容.文本 & "\n"
  调用 File1.追加文件(追加内容, "/sdcard/MyApp/log.txt")

写入JSON数据

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

读取文件

基本读取

当 按钮_读取.被点击
  调用 File1.读取文件("/sdcard/MyApp/notes.txt")

当 File1.收到文本(内容)
  标签_内容.文本 = 内容

读取并解析JSON

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

逐行处理

当 File1.收到文本(内容)
  设 行列表 = 分割文本(内容, "\n")
  设 i = 1
  当 i ≤ 列表长度(行列表)
    设 当前行 = 列表第i项(行列表)
    ' 处理每一行...
    设 i = i + 1

CSV文件操作

写入CSV

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

读取CSV

当 File1.收到文本(内容)
  设 行列表 = 分割文本(内容, "\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)

使用示例

' 复制文件到相册
当 按钮_保存到相册.被点击
  调用 FileTools1.复制文件(图片路径, "/sdcard/DCIM/Camera/photo_" & 时间戳 & ".png")
  调用 FileTools1.扫描文件("/sdcard/DCIM/Camera/photo_" & 时间戳 & ".png")

' 列出目录文件
当 按钮_列出文件.被点击
  调用 FileTools1.列出文件("/sdcard/MyApp/")

当 FileTools1.文件列表(文件列表)
  设 显示 = ""
  设 i = 1
  当 i ≤ 列表长度(文件列表)
    设 显示 = 显示 & 列表第i项(文件列表) & "\n"
    设 i = i + 1
  标签_文件列表.文本 = 显示

存储照片

从Camera保存到指定路径

当 按钮_拍照.被点击
  调用 相机1.拍照()

当 相机1.拍照完成(图片路径)
  ' 复制到自己的目录
  设 新路径 = "/sdcard/MyApp/photos/" & Clock1.格式化日期时间(Clock1.当前时间(), "yyyyMMdd_HHmmss") & ".jpg"
  调用 FileTools1.复制文件(图片路径, 新路径)
  标签_状态.文本 = "✅ 照片已保存:" & 新路径

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

当 按钮_存相册.被点击
  调用 FileTools1.保存到相册(图片路径)
  ' FileTools会自动通知系统扫描

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

常见问题

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

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

  • ReadWriteExternalStorage = true

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

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

调用 File1.读取文件(目标路径)

当 File1.收到文本(内容)
  如果 内容 = ""
    标签_状态.文本 = "文件不存在或为空"
  否则
    标签_状态.文本 = "文件存在"

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 🐝 整理。

文档反馈