Котлин эквивалентен БитАррею C#

#c# #.net #spring #kotlin

Вопрос:

Я работаю с приложением .NET, которое хранит длинный список истинных/ложных значений в BitArray, который хранится на сервере SQL в виде двоичного(32) значения. Данные возвращаются из базы данных в виде байта[].

Я пытаюсь перенести проект в Котлин с помощью Spring. После долгих тестов и возни я, наконец, смог получить в Kotlin тот же массив, что и в BitArray в C#. Однако это решение кажется довольно сложным, просто чтобы получить массив true / false значений из ByteArray.

Я уверен, что есть более чистый способ сделать это, но я все еще изучаю Котлин, и вот что я придумал:

 fun convertByteArrayToBitArray(array: ByteArray): List<Boolean>{
        val stringBuilder = StringBuilder()
        array.forEach {
            // Convert to Integer to convert to binaryString
            var int = it.toInt()

            // Because the array has signed values, convert to unsigned value. Either this or add 
            // '.takeLast(8)' to the end of the String.format call
            if(int < 0) int  = 256

            // Convert to binary string padding with leading 0s
            val binary = String.format("%8s", Integer.toBinaryString(int)).replace(" ", "0")

            // Through testing, this binary value needs to be reversed to give the right values
            // at the right index
            stringBuilder.append(binary.reversed())
        }

        // Convert stringBuilder to CharArray then to List of true/false values
        return stringBuilder.toString().toCharArray().map {
            Integer.parseInt(it.toString()) == 1
        }
}
 

Ответ №1:

Если вам не нужен мультиплатформенный код, вы можете использовать набор битов из Java stdlib:

 val bytes = byteArrayOf(0x11, 0x11)
val bits = BitSet.valueOf(bytes)

println(bits[0]) // true
println(bits[1]) // false
println(bits[4]) // true
println(bits[5]) // false
println(bits[8]) // true
println(bits[9]) // false

val bytes2 = bits.toByteArray()
 

Он хранит данные в литтл-эндиане. Если я правильно прочитал ваш код, он также использует файл.

Если вам нужно List<Boolean> конкретно, например, потому, что часть вашего кода уже зависит от него, вы можете конвертировать между BitSet и List<Boolean> так:

 fun BitSet.toBooleanList() = List(length()) { this[it] }

fun List<Boolean>.toBitSet() = BitSet(size).also { bitSet ->
    forEachIndexed { i, item ->
        bitSet.set(i, item)
    }
}
 

Просто обратите List<Boolean> внимание, что это очень неэффективно для памяти.

Комментарии:

1. Вау… Я почти чувствую себя глупо из-за того, насколько простым было решение для этого. Большое спасибо!

2. И если вам действительно нужен логический список… fun BitSet.toBooleanList() = List<Boolean>(length(), ::get)

3. @Tenfour04 Да, я уже добавил это 😉

4. Ой. Но вам нужно использовать length() вместо size() этого .

5. Да, вы правы. На самом деле, я думаю, что это было бы лучше всего получить 16 при преобразовании из массива в два байта, но я думаю BitSet , что такая информация не хранится. Тогда length() имеет больше смысла, чем size() . Спасибо.