I'm moving from Android Studio to flutter. In the Android Studio project , I write files in a JSON format using this code:
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();
}
I now want to load in these files in Flutter SDK using this code
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 [];
}
But the problem is that the string jsonstr
is now prefixed by weird characters. Here's how it is saved and loaded in at Android Studio
{"property1":"value1", ...}
and this is how it's read in in Flutter SDK
’ t${"property1":"value1", ... }
I also tried using utf8 encoding but this raises an exception
Failed to decode data using encoding 'utf-8'
So how to get the normal JSON string without the weird symbols before it?
Your title says "reading in text file...", but of course you aren't reading in a text file - you are reading in a Java object serialization, as created by ObjectOutputStream.writeObject()
. So now you need to read and interpret that format .
As you've written a single string, the output will consist of the stream header, then a string
identifier plus the length of the string, then the string.
Create a method to read the file and parse the header:
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));
}
and call it from your loop:
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;
}
or like this
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))));
}
Note that there's a bug in your version. You only add members to items
in the then
which won't get executed until the future. It's simpler to get right with the await
syntax.
您还需要在Java代码中使用utf8编码写入文件:
ObjectOutputStream os = new ObjectOutputStream(fos, StandardCharsets.UTF_8));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.