Flutter/Dart:读取文本文件以奇怪的字符为前缀
Posted
技术标签:
【中文标题】Flutter/Dart:读取文本文件以奇怪的字符为前缀【英文标题】:Flutter/Dart : reading in text file is prefixed by weird characters 【发布时间】:2020-01-19 12:38:36 【问题描述】:我正在从 android Studio 迁移到 Flutter。在 Android Studio 项目中,我使用以下代码以 JSON 格式编写文件:
String json = gson.toJson(item);
FileOutputStream fos = null;
try
fos = context.openFileOutput("item"+ item.getUid(), Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(json);
os.close();
fos.close();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
我现在想使用此代码在 Flutter SDK 中加载这些文件
Future<List<Item>> loadAllItems() async
try
var items = <Item>[];
var filesDir = Directory("/data/user/0/com.company.app/files");
for(var f in filesDir.listSync())
if(f is File)
f.readAsString(encoding: latin1).then((jsonstr) =>
items.add(parse(jsonstr))
);
return items;
catch(e)
log(e);
return [];
但问题是字符串jsonstr
现在以奇怪的字符为前缀。
这是它在 Android Studio 中的保存和加载方式
"property1":"value1", ...
这就是它在 Flutter SDK 中的读取方式
’ t$"property1":"value1", ...
我也尝试过使用 utf8 编码,但这会引发异常
使用编码“utf-8”解码数据失败
那么如何获取前面没有奇怪符号的普通 JSON 字符串呢?
【问题讨论】:
这三个字符不是告诉ObjectInputStream
后面字节的java类型的前缀吗?它们看起来像来自docs.oracle.com/javase/8/docs/platform/serialization/spec/… 的流魔术字节。您需要将它们剪掉(它们应该始终相同 - 考虑到 2 个字节对字符串长度进行编码),然后 UTF-8 解码其余部分。
【参考方案1】:
您的标题是“正在读取文本文件...”,但您当然不是在读取 text 文件 - 您正在读取由 @987654322 创建的 Java 对象序列化@。所以现在你需要阅读和解释that format。
当您编写单个字符串时,输出将包含流标头,然后是 string
标识符加上字符串的长度,然后是字符串。
创建一个读取文件并解析头部的方法:
Future<String> readJavaObjectFile(File file) async
var bytes = await file.readAsBytes() as Uint8List;
var data = bytes.buffer.asByteData();
assert(data.getUint16(0) == 0xaced); // stream_magic
assert(data.getUint16(2) == 5); // stream_version
assert(bytes[4] == 0x74); // tc_string
var length = data.getUint16(5); // length thereof
return utf8.decode(bytes.sublist(7, 7 + length));
并从您的循环中调用它:
Future<List<Item>> loadAllItems(Directory filesDir) async
var items = <Item>[];
for (var f in await filesDir.list().where((e) => e is File).toList())
items.add(parse(await readJavaObjectFile(f)));
return items;
或者像这样
Future<List<Item>> loadAllItems(Directory filesDir) async
var files = await filesDir.list().where((e) => e is File).toList();
return await Future.wait(
files.map<Future<Item>>((f) async => parse(await readJavaObjectFile(f))));
请注意,您的版本中存在错误。您只需将成员添加到then
中的items
,直到将来才会执行。使用await
语法更简单。
【讨论】:
【参考方案2】:您还需要在您的 java 代码中写入带有 utf8 编码的文件:
ObjectOutputStream os = new ObjectOutputStream(fos, StandardCharsets.UTF_8));
【讨论】:
那么默认编码是什么?而且由于这已经太晚了(应用程序已经部署到成千上万的用户并且需要保留他们的数据),有什么办法可以解决这个问题? 我快速搜索了一下,发现了这个:***.com/questions/4390457/…@WouterVandenpette以上是关于Flutter/Dart:读取文本文件以奇怪的字符为前缀的主要内容,如果未能解决你的问题,请参考以下文章