Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Protobuf format error: input ended unexpectedly in the middle of a field

I am parsing a GftsRealtime feed using google protobuf parser. Here is the exact error I am encountering: com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either than the input has been truncated or that an embedded message misreported its own length. First thought that comes to mind is that the integrity of the file was compromised while downloading but I check the file in the Android emulator against the one I download on the desktop and it's the same. Has anyone encountered this issue before? I am using version '0.0.4' of the gfts-realtime-parser. The feed is here.

EDIT ----

Here is the code I use to download the file:

override fun doInBackground(vararg urls: URL): Boolean? {
        val httpClient = OkHttpClient()
        val call = httpClient.newCall(Request.Builder().url(urls[0]).get().build())
        val urlStr = urls[0].toString()
        val fileName = urlStr.substring(urlStr.lastIndexOf('/') + 1, urlStr.length)
        val file = File(context.filesDir, fileName)
        try {
            val response = call.execute()
            if (response.code() === 200) {
                var inputStream: InputStream? = null
                val outputStream = FileOutputStream(file)
                try {
                    inputStream = response.body().byteStream()
                    val buff = ByteArray(1024 * 4)
                    var downloaded: Long = 0
                    val target = response.body().contentLength()
                    publishProgress(0L, target)
                    while (true) {
                        val readed = inputStream!!.read(buff)
                        if (readed == -1) {
                            break
                        }
                        outputStream.write(buff, 0, readed)
                        //write buff
                        downloaded += readed.toLong()
                        publishProgress(downloaded, target)
                        if (isCancelled()) {
                            fileListener(null)
                            return false
                        }
                    }
                    fileListener(file)
                    return downloaded == target
                } catch (ignore: IOException) {
                    fileListener(null)
                    return false
                } finally {
                    if (inputStream != null) {
                        inputStream!!.close()
                    }
                    outputStream.flush()
                    outputStream.close()
                }
            } else {
                fileListener(null)
                return false
            }
        } catch (e: Exception) {
            e.printStackTrace()
            fileListener(null)
            return false
        }
    }

EDIT 2 ---- Here is the complete code path

override fun onHandleIntent(intent: Intent?) {
        Realm.init(applicationContext)
        val config = RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().build() // TODO remove before deploy
        RealmInstace = Realm.getInstance(config)

        Timber.i("Realm file path: ", RealmInstace?.path)
        val action = intent?.action
        when (action) {
            ACTION_UPDATE_GFTS -> updateGfts()
            ACTION_UPDATE_GFTS_REALTIME -> updateGftsReal() // this is called
            REALM_GET_ALL_TRAIN_MAP -> getTrainMapData(intent)
        }
        exportDatabase()
//        RealmInstace?.close()
        RealmInstace = null
    }

private fun updateGftsReal() {
        var file:File?=null
        AsyncDownloader(this, null, { f ->
            file = f
            if(file!=null && file!!.exists())
                GftsRealRealmParser(applicationContext, file!!, RealmInstace!!)
            else
                Timber.e("Failed to download trip updates", GFTS_REALTIME_TRIP_URL)
        }).execute(URL(GFTS_REALTIME_TRIP_URL)).get(2, TimeUnit.MINUTES)
    }

class GftsRealRealmParser(val context: Context, val file: File, val realm: Realm) {
    init {
        var feedr: FeedMessageR? = null
        var inputStream = BufferedInputStream(FileInputStream(file))
        try {
            val url = URL("http://developer.mbta.com/lib/GTRTFS/Alerts/TripUpdates.pb")
            val feed = GtfsRealtime.FeedMessage.parseDelimitedFrom(url.openStream())
            feedr = FeedMessageR(feed)
            realm.executeTransaction {
                Timber.i("Committing ${feedr!!.entityList.size} to the realtime db.")
                realm?.copyToRealm(feedr)
//                val train = realm.where(TripDescriptorR::class.java).contains("route_id", "31760754").findFirst()
            }
        } catch (e: IOException) {
            Timber.e(e.message, e)
            e.printStackTrace()
        } catch(e: Exception) {
            Timber.e(e.message, e)
            e.printStackTrace()
        }
        if (feedr == null)
            throw ParseException("Failed to parse file", 0)
    }
}

EDIT 4 ----

see answer below

like image 415
SomethingsGottaGive Avatar asked Oct 18 '22 16:10

SomethingsGottaGive


1 Answers

I found the solution. I was calling the wrong funtion. I was calling parseDelimitedFrom where I should've been calling parseFrom.

like image 198
SomethingsGottaGive Avatar answered Oct 21 '22 05:10

SomethingsGottaGive