You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter加载JSON资源报错:No such file or directory(errno=2)求助

问题描述

我正在开发一款用于测试自身技能的Flutter应用,但在导入项目中位于assets/repository/translation.json的JSON文件时遇到错误。应用能正常启动,但点击章节查看译文时会出现范围错误,推测是翻译列表为空导致的。

相关代码

TranslationService类

import 'dart:convert';
import 'dart:io';

import 'package:islam_plus/models/translation_model.dart';
import 'package:quran/quran.dart' as quran;

class TranslationService {
  final String _filePath = 'assets/repository/translation.json';

  List<AyahTranslation> translationList = [];

  Future<void> loadTranslations() async {
    final jsonString = await File(_filePath).readAsString();
    print(jsonString);
    final jsonBody = jsonDecode(jsonString);
    print(jsonBody);
    final List<dynamic> quranList = jsonBody['quran'];

    translationList = quranList
        .map((dynamic item) => AyahTranslation.fromJson(item))
        .toList();
  }

  List<AyahTranslation> getAyahTranslation(int surahNumber) {
    final totalVerseCount = quran.getVerseCount(surahNumber);
    int verseCount = 1;

    final translationFiltered = translationList.where((translation) {
      if (surahNumber == translation.chapter) {
        verseCount++;

        if (verseCount > totalVerseCount) {
          verseCount = 1;
        }
        return true;
      }
      return false;
    }).toList();
    return translationFiltered;
  }

  String getRandomTranslation(int surahNumber, int verseNumber) {
    final translationList = getAyahTranslation(surahNumber);
    final translation = translationList.firstWhere(
        (translation) => translation.verse == verseNumber,
        orElse: () => AyahTranslation(
            chapter: surahNumber,
            verse: verseNumber,
            text: 'Translation Not found'));

    return translation.text;
  }
}

pubspec.yaml配置

flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/images/number_star.png
    - assets/repository/translation.json

  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware

主页面initState代码

class _QuranPageState extends State<QuranPage> with TickerProviderStateMixin {
  final service = QuranService();
  late TabController _tabController;
  TranslationService _translationService = TranslationService();

  onTabChange(int index) {}

  @override
  void initState() {
    _translationService.loadTranslations();
    _tabController = TabController(length: 4, vsync: this);
    super.initState();
  }
}

运行错误

E/flutter (10333): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PathNotFoundException: Cannot open file, path = 'assets/repository/translation.json' (OS Error: No such file or directory, errno = 2)
解决方案

1. 替换File读取方式为rootBundle加载assets

Flutter的assets文件是嵌入应用包内的资源,不能直接用File类读取,必须通过rootBundle加载:

修改TranslationService的代码:

import 'dart:convert';
// 移除dart:io的导入
import 'package:flutter/services.dart'; // 新增导入
import 'package:islam_plus/models/translation_model.dart';
import 'package:quran/quran.dart' as quran;

class TranslationService {
  final String _filePath = 'assets/repository/translation.json';

  List<AyahTranslation> translationList = [];

  Future<void> loadTranslations() async {
    // 用rootBundle加载assets文件
    final jsonString = await rootBundle.loadString(_filePath);
    print(jsonString);
    final jsonBody = jsonDecode(jsonString);
    print(jsonBody);
    final List<dynamic> quranList = jsonBody['quran'];

    translationList = quranList
        .map((dynamic item) => AyahTranslation.fromJson(item))
        .toList();
  }

  // 其余方法保持不变
}

2. 确认assets文件和路径有效性

  • 检查项目中assets/repository/translation.json是否真实存在,路径大小写需和代码、pubspec.yaml完全一致(Flutter对路径大小写敏感)。
  • 执行flutter pub get确保assets配置生效,必要时重启IDE或热重载应用。

3. 处理异步加载的等待逻辑

当前initState中直接调用异步方法但未等待完成,会导致用户操作时数据还没加载好。可以添加加载状态提示:

修改主页面代码:

class _QuranPageState extends State<QuranPage> with TickerProviderStateMixin {
  final service = QuranService();
  late TabController _tabController;
  TranslationService _translationService = TranslationService();
  bool _isLoading = true; // 新增加载状态标记

  onTabChange(int index) {}

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 4, vsync: this);
    // 单独封装异步加载方法并更新状态
    _loadTranslations();
  }

  Future<void> _loadTranslations() async {
    await _translationService.loadTranslations();
    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator()); // 加载中提示
    }
    // 原页面的build代码
    return ...;
  }
}

内容的提问来源于stack exchange,提问作者Sgt Puke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 11:17:14