Ошибка с "нарезкой" string kotlin
При выборе файла через onActivityResult() я хочу "нарезать" его на куски. Для этого я считываю его байты:
val fileUri = data.data!!
val string = fileUri.let { uri -> contentResolver.openInputStream(uri).use { it!!.readBytes() } }
и провожу "нарезку":
val partSize = 10000
val partsCount = if (size.rem(partSize).toInt() == 0) {
size.div(partSize).toInt()
} else {
size.div(partSize).toInt() + 1
}
for (i in 0 until partsCount) {
val slicedString: ByteArray = if ((i + 1) * partSize < i * partSize + size.rem(partSize).toInt()) {
string.slice(i * partSize..(i + 1) * partSize).toByteArray()
} else {
string.slice(i * partSize..i * partSize + size.rem(partSize).toInt()).toByteArray()
}
}
а теперь собственно проблема: размер файла 127036 а у меня приложение падает с ошибкой:
java.lang.IndexOutOfBoundsException: toIndex (127037) is greater than size (127036)
Вопрос - откуда еще один байт взялся, и как его убрать? Может это какой-то пробел или невидимый символ, который нужно убирать через trim()? Если брать обычный вывод в консоль идексов для нарезки то все нормально:
if ((i + 1) * partSize < i * partSize + size.rem(partSize).toInt()) {
Timber.i((i * partSize..(i + 1) * partSize).toString())
} else {
Timber.i((i * partSize..i * partSize + size.rem(partSize).toInt()).toString())
}
Допускаю что проблема где-то в size.rem(partSize).toInt(). Округлить не получается, потому что передается long а в документации есть только double/int. Есть так же идея сдвинуть на один бит:
size.rem(partSize).shr(1).toInt()
но не уверен что это правильное решение.
Ответы (1 шт):
Простой тест показывает где именно ошибка.
val i = 1
val partSize = 7
val size = "1234567890".length
println(i * partSize..i * partSize + size.rem(partSize).toInt())
// 7..10
"1234567890".slice(7..10)
// Exception
slice вырезает интервал ОТ-ДО включительно. Соответственно границу ДО нужно высчитывать не забывая, что значение длины строки не является ее последним индексом.
Верным мне видится такой код:
val slicedString: ByteArray = if ((i + 1) * partSize < size) {
string.slice(i * partSize..(i + 1) * partSize).toByteArray()
} else {
string.slice(i * partSize..(size - 1)).toByteArray()
}