Ошибка с "нарезкой" 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 шт):

Автор решения: Eugene Krivenja

Простой тест показывает где именно ошибка.

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()
}
→ Ссылка