Чтение большого файла двоичных данных кусками по 1024 байта - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь прочитать файл MP4 кусками по 1024 байта. Я сделал код, который - почти - работает. Я делаю следующее:

let audioFilePath = Bundle.main.path(forResource: "video", ofType: "mp4")!
var chunks = [[UInt8]]()

  if let stream: InputStream = InputStream(fileAtPath: audioFilePath) {
    var buf: [UInt8] = [UInt8](repeating: 0, count: 1024)
    stream.open()
    while stream.hasBytesAvailable {
      stream.read(&buf, maxLength: 1024)
      chunks.append(buf)
    }
    stream.close()
  }

print(chunks.count)

Проблема с кодом выше заключается в том, что я читаю файл MP4 размером 15,948,514 байт. Это означает, что он должен заканчиваться sh ровно 15,574 чанками (последний чанк может иметь меньше 1024, но это не проблема), но код печатает 15,576 чанков, и все они имеют размер 1024. Что не так с код выше?

1 Ответ

1 голос
/ 24 апреля 2020

hasBytesAvailable также может возвращать true, если необходимо выполнить чтение для определения доступности байтов. Вот что происходит в вашем случае: конечное чтение возвращает ноль для «конца файла».

hasBytesAvailable может быть полезно с входными потоками, такими как сокеты TCP, чтобы избежать блокировки read(), но на самом деле это не так необходимо для чтения из файлов. В любом случае вы должны проверить возвращаемое значение read(), которое может быть нулем (конец файла) или -1 (ошибка чтения), или фактическим количеством байтов, считанных в буфер (которое может быть меньше, чем число запрошено байтов).

Обратите также внимание, что вы всегда добавляете чанк с 1024 байтами в массив chunks, даже если буфер только частично заполнен байтами из входного потока.

if let stream = InputStream(fileAtPath: audioFilePath) {
    var buf = [UInt8](repeating: 0, count: 1024)
    stream.open()

    while case let amount = stream.read(&buf, maxLength: 1024), amount > 0 {
        // print(amount)
        chunks.append(Array(buf[..<amount]))
    }
    stream.close()
}
...