Here's my problem. In my DetailActivity I check to see whether a File is empty or not. If it is, I create a new File and write an object to that file no problem. If it isn't, this means the file has a List of data objects written to it like so:
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(...)
If the File has an object written to it, I want to essentially append a new data object to that List. To do that, I read the file, assign the List I read from the file to a new variable and then re-write it to the file.
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()
}
The problem: once the File has been written to, I want to read it from another Activity so I can display it in a RecyclerView. But when I read the File, it doesn't include any of the data objects added to the newList
I recently wrote into the file. It only includes the data objects in the previousList
, which is stale data by this point.
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()
}
What is happening here? I've spent hours trying to debug this to no avail. Any help would be greatly appreciated. Thank you in advance :)
After some further reading, I discovered it's not possible to append data to an already existing file because ObjectOutputStream
adds a header to any and all writes it makes to a file.
Calling ObjectOutputStream.writeObject(data)
multiple times on the same file will result in a corrupted file due to the presence of multiple headers. When ObjectInputStream
subsequently reads the file, it isn't smart enough to parse out all the extra stuff that gets written onto the file (such as the header). Refer here for documentation.
To get around this, I simply recreated a new file using file.createNewFile()
and wrote the new data to it. Because the file was essentially "recreated", all the header information from previous writes no longer exist - it is a blank file with the same name.
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
Given I spent several hours trying to debug this, I hope this manages to help someone later down the track!