附加到 ObjectOutputStream 不会改变任何东西

Appending to ObjectOutputStream does not change anything

这是我的问题。在我的 DetailActivity 中,我检查文件是否为空。如果是,我创建一个新文件并将对象写入该文件没问题。如果不是,这意味着该文件有一个写入数据对象的列表,如下所示:

try{
      val file = File(filesDir, "Example Shelf")
      val outputStream = openFileOutput(file.name, Context.MODE_APPEND)
      if(file.length() != 0.toLong()){
           val inputStream = openFileInput(file.name)
           gameDetailViewModel.addGameToExistingShelf(outputStream, inputStream, data)
      } else {
           file.createNewFile()
           gameDetailViewModel.addGameToNewShelf(outputStream, data)
      } catch(...)

如果文件中写入了一个对象,我基本上想将一个新的数据对象附加到该列表中。为此,我读取了文件,将从文件中读取的列表分配给一个新变量,然后将其重新写入文件。

fun addGameToExistingShelf(fos: FileOutputStream, fis: FileInputStream, data: GameData){
        val previousList = ObjectInputStream(fis).readObject() as MutableList<GameData>
        val newList = previousList
        newList.add(data)
        ObjectOutputStream(fos).writeObject(newList)
        fos.close()
        fis.close()
}

问题:一旦文件被写入,我想从另一个Activity读取它,这样我就可以在 RecyclerView 中显示它。但是当我读取文件时,它不包括添加到我最近写入文件的 newList 的任何数据对象。它仅包括 previousList 中的数据对象,这是此时的陈旧数据。

val file = File(filesDir, "Example Shelf")
if(file.isFile && file.length() != 0.toLong()){
  val inputStream = openFileInput(file.name)
  shelfViewModel.fetchShelfData(inputStream)
}

ShelfViewModel.fetchShelfData

fun fetchShelfData(fis: FileInputStream){
    val objis = ObjectInputStream(fis)
    //MutableLiveData<List<GameData>>
    shelfData.value = objis.readObject() as List<GameData>
    objis.close()
}

这里发生了什么?我花了几个小时试图调试它无济于事。 任何帮助将不胜感激。提前谢谢你:)

进一步阅读后,我发现无法将数据附加到已存在的文件中,因为 ObjectOutputStream 将 header 添加到它对文件的所有写入操作。

对同一文件多次调用 ObjectOutputStream.writeObject(data) 将导致文件损坏,因为存在多个 header。当 ObjectInputStream 随后读取文件时,它不够聪明,无法解析出写入文件的所有额外内容(例如 header)。请参阅 here 文档。

为了解决这个问题,我只是使用 file.createNewFile() 重新创建了一个新文件并将新数据写入其中。因为文件本质上是“重新创建的”,所以以前写入的所有 header 信息都不再存在 - 它是一个同名的空白文件。

if(file.length() != 0.toLong()){
   val fileInput = openFileInput(file.name)
   val newData = gameDetailViewModel.fetchDataFromExistingShelf(fileInput, data)
   file.createNewFile() //File is recreated
   val fileOutput = openFileOutput(file.name, Context.MODE_PRIVATE)
   gameDetailViewModel.writeObjectToFile(fileOutput, newData) //Object is written to new, recreated file

考虑到我花了几个小时尝试调试它,我希望它能帮助后来的人!