防止多次读取文件

时间:2014-06-19 09:07:38

标签: dart

我正在尝试编写一个i18n应用程序。该程序读取一个json文件,该文件包含来自语言的翻译,它基于json结构。

{
    "EN": {
        "TEXT1": "Hello",
        "TEXT2": "March"
    },
    "DE": {
        "TEXT1": "Hallo",
        "TEXT2": "März"
    }
}

我的程序使用文件类,整个代码

以异步方式读取json文件
import 'dart:io';
import 'dart:async';
import 'package:json_object/json_object.dart';

abstract class I18n {

  static _I18n _i18n;

  factory I18n(String file, String lang) {
      if(_i18n == null) {

          _i18n = new _I18n(file, lang);
          return _i18n;
      }

      return _i18n;
  }


  Future<String> getTextByMap(String textId);

}

class _I18n implements I18n {

    File _file;
    String _lang;
    JsonObject _jsonContainer;
    JsonObject _jsonFiltered;
    Future<JsonObject> _imme;

    // Parameters:
    // file: The whole path and filename
    // lang: Expected language
    _I18n(String file, this._lang) {
        this._file = new File(file);
    }

    // Read file and return the content of file.
    Future<String> _readFileFromStream() {
        var com = new Completer();
        this._file.exists()
            .then((fileExists) {

                if(!fileExists) {
                    throw new StateError('File not found');
                }
                return this._file.readAsString()
                    .then((stream) => com.complete(stream));
            });
        return com.future;
    }

    void _convertContentToJson(String stream) {
        this._jsonContainer = new JsonObject.fromJsonString(stream);
    }


    Future<JsonObject> _prepareData() {
        return this._readFileFromStream().then((stream) {
            _convertContentToJson(stream);
            this._jsonFiltered = this._jsonContainer[this._lang];
            return this._jsonFiltered;
        });
    }


    Future<String> getTextByMap(String textId) {
        return this._prepareData().then((filterd) {
           return filterd[textId];
        });
    }
}

和主要代码

import 'package:i18n/i18n.dart';


void main() {
    var i18n = new I18n('../hello.json', 'EN');
    i18n.getTextByMap('TEXT1').then((val) => print(val));
    i18n.getTextByMap('TEXT2').then((val) => print(val));
}

这里的一切,以dart async方式发生,读取json文件等。每当我调用方法时

i18n.getTextByMap('TEXT1').then((val) => print(val));

它会一次又一次地读取json文件。我试图重写该方法以防止多次读取json文件

Future<String> getTextByMap(String textId) {
    if(this._jsonFiltered == null)
    {
        return this._prepareData().then((filterd) {
           return filterd[textId];
        });
    }
    return new Future(() => this._jsonFiltered[textId]);
}

但它也不起作用,因为dart以异步方式工作。

我的问题是,如何将这个json文件内容保存在对象中?只读一次json文件并将内容保存在一个对象中,最好每次都读取json文件,这是我的看法。

它可以以同步方式完成所有事情,然后我就不会有问题,但这不是dart术语。

dart执行I / O操作的顺序是什么顺序?

  
      
  1. 未来
  2.   
  3. I / O活动
  4.   

1 个答案:

答案 0 :(得分:3)

我的解决方案是使用工厂构造函数创建一个类。工厂构造函数始终返回该文件的对象。

你的问题是期货是平行的。因此两个调用都是并行执行的。解决方案是让第一个未来完成,然后做其他事情以获得缓存结果。

然后你可以有一个read()方法读取文件的值,如果它不存在于类&#34;内容&#34;例如属性 - 或者如果该属性不为null,则它在后台加载文件。

在这两种情况下,您都可以收听完成者或未来。

编辑示例代码:

example_async_file_factory.dart

import 'dart:io';
import 'dart:async';

class FileHolder {
  String _contents = null;

  String path;

  static Map<String, FileHolder> _files;

  factory FileHolder(String path) {
    if (_files == null) {
      _files = {};
    }

    if (_files.containsKey(path)) {
      return _files[path];
    } else {
      final fh = new FileHolder._internal(path);
      _files[path] = fh;
      return fh;
    }
  }

  FileHolder._internal(this.path);

  Future<String> getContents() {
    if(_contents != null) {
      print("cached");
      return new Future.value(_contents);
    } else {
      print("read");
      File f = new File(this.path);
      Future<String> future = f.readAsString();
      Completer completer = new Completer();
      future.then((String c) {
        _contents = c;
        completer.complete(_contents);
      });
      return completer.future;
    }
  }
}

void main() {
  FileHolder f = new FileHolder("example_async_file_factory.dart");
  f.getContents().then((String contents) {
    print(contents.length);

    FileHolder f2 = new FileHolder("example_async_file_factory.dart");
      f2.getContents().then((String contents) {
        print(contents.length);
      });
      f2.getContents().then((String contents) {
          print(contents.length);
        });
      f.getContents().then((String contents) {
          print(contents.length);
        });
  });
}

输出:

read
1411
cached
cached
cached
1411
1411
1411

此致 罗伯特