如何在 Kotlin 中将对象转换为字节数组

5

我有一个 Kotlin 对象,需要将其转换为字节数组 (byte[])。我知道如何将字符串和一系列其他类型的变量转换为 byte[],但我找不到任何关于如何使用对象进行此操作的内容。

这是我尝试过的:

override fun activateQuestion(instructorUserName: String, host: String, port: Int, questionToActivate: MultipleChoiceQuestion) {
        val socket = DatagramSocket()

        //This is the problem -- `.toByteArray(...)` only works for Strings
        val questionToActivateAsByteArray = questionToActivate.toByteArray(Charsets.UTF_8)

        //send byte[] data 
        val packet = DatagramPacket(questionToActivateAsByteArray, questionToActivateAsByteArray.size, InetAddress.getByName(host), port)
        socket.send(packet)
    }

1
https://dev59.com/4lLTa4cB1Zd3GeqPXRka - IR42
我通常选择在网络上传输对象时使用JSON。这使您能够在任何语言中对其进行解码。我会使用Jackson的ObjectMapper,并将您的对象转换为字符串后作为字节发送。 - flakes
你找到解决方案了吗?我也在想同样的问题。 - IgorGanapolsky
3个回答

4

使用Kotlinx的序列化是我发现的最简单的方法:

在您的数据类上标记@Serializable(如果此方法无效,请将必要的插件和依赖项添加到您的build.gradle文件中)。

@Serializable
data class User(val name: String, val age: Int)

当你创建一个实例时,你可以通过Json.encodeToString(yourInstance).toByteArray()将其转换为Json字符串并转换为字节数组。

例如:

val user = User(Mohammed, 25)
val userAsByteArray = Json.encodeToString(user).toByteArray()

4

您可以按照Java风格将其转换为字节数组。类似于以下内容:Java可序列化对象转换为字节数组

编辑: 为使其更易于理解,其实用函数将如下所示:

import java.io.*

@Suppress("UNCHECKED_CAST")
fun <T : Serializable> fromByteArray(byteArray: ByteArray): T {
    val byteArrayInputStream = ByteArrayInputStream(byteArray)
    val objectInput: ObjectInput
    objectInput = ObjectInputStream(byteArrayInputStream)
    val result = objectInput.readObject() as T
    objectInput.close()
    byteArrayInputStream.close()
    return result
}

fun Serializable.toByteArray(): ByteArray {
    val byteArrayOutputStream = ByteArrayOutputStream()
    val objectOutputStream: ObjectOutputStream
    objectOutputStream = ObjectOutputStream(byteArrayOutputStream)
    objectOutputStream.writeObject(this)
    objectOutputStream.flush()
    val result = byteArrayOutputStream.toByteArray()
    byteArrayOutputStream.close()
    objectOutputStream.close()
    return result
}

使用它们只需像这样做:

val yourSerializableObject = YourSerializableObject(...)
val objectInByteArrayFormat = yourSerializableObject.toByteArray()
val convertedObject = fromByteArray<YourSerializableObject>(objectInByteArrayFormat)

不要忘记你的对象及其所有属性必须是可序列化的


2
下面是一个可序列化的对象类,在Kotlin中将对象转换为字节数组和反向操作非常有帮助。
public class ObjectSerializer {
    companion object {
        public fun serialize(obj: Any?) : String {
            if (obj == null) {
                return ""
            }

            var baos = ByteArrayOutputStream()
            var oos = ObjectOutputStream(baos)
            oos.writeObject(obj)
            oos.close()

            return encodeBytes(baos.toByteArray())
        }

        public fun deserialize(str: String?) : Any? {
            if (str == null || str.length() == 0) {
                return null
            }

            var bais = ByteArrayInputStream(decodeBytes(str))
            var ois = ObjectInputStream(bais)

            return ois.readObject()
        }

        private fun encodeBytes(bytes: ByteArray) : String {
            var buffer = StringBuffer()

            for (byte in bytes) {
                buffer.append(((byte.toInt() shr 4) and 0xF plus 'a').toChar())
                buffer.append(((byte.toInt()) and 0xF plus 'a').toChar())
            }

            return buffer.toString()
        }

        private fun decodeBytes(str: String) : ByteArray {
            var bytes = ByteArray(str.length() / 2)

            for (i in 0..(str.length() - 1)) {
                var c = str.charAt(i)
                bytes.set(i / 2, ((c minus 'a').toInt() shl 4).toByte())

                c = str.charAt(i + 1)
                bytes.set(i / 2, (bytes.get(i / 2) + (c minus 'a')).toByte())
            }

            return bytes
        }
    }
}

当我把你的代码复制到我的本地IDE时,有些依赖项无法正常工作。请问能否提供相关的导入包部分? - Lysander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接