如何在 iOS 文件系统中存储来自 UnsafeMutablePointer 的数据
How to store data from an UnsafeMutablePointer in the iOS file system
我正在使用第 3 方 SDK "sessionController" 从 MFi 外部设备将数据读取到缓冲区中。见下文:
let handle: UInt64 = self.sessionController.openFile(file.path, mode: openMode)
if handle == 0 {
//Error
return
}
let c: UInt64 = file.size
var bytesArray: [UInt8] = [UInt8](fileData)
let bufferPointer: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(c))
bufferPointer.initialize(repeating: 0, count: Int(c))
defer {
bufferPointer.deinitialize(count: Int(c))
bufferPointer.deallocate()
}
var sum: UInt32 = 0
let singleSize: UInt32 = 8 << 20
while sum < c {
let read = self.sessionController.readFile(handle, data: bufferPointer, len: singleSize)
if read == 0 {
//There was an error
return
}
sum += read
}
let newPointer : UnsafeRawPointer = UnsafeRawPointer(bufferPointer)
fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("test.MOV")
fileData = Data(bytes: newPointer, count: Int(c))
try! fileData.write(to: fileURL)
//Now use this fileURL to watch video in an AVPlayer...
//AVPlayer(init: fileURL)
由于某种原因,存储在 fileURL 的数据已损坏(我认为),我无法播放视频文件。我想我没有正确地使用 Unsafe Swift 做一些事情,但我不确定是什么。我怎样才能确保我已经正确地将数据从设备读取到内存中,然后从内存中取出该数据并将其存储在硬盘驱动器的 fileURL 中?我在这里做错了什么?给定 fileURL,视频将不会在 AVPlayer 中播放。
主要错误在这里:
let read = self.sessionController.readFile(handle, data: bufferPointer, len: singleSize)
如果您读取多个块,那么第二次和所有后续读取将覆盖 之前读取的数据。所以应该是
let read = self.sessionController.readFile(handle, data: bufferPointer + sum, len: singleSize)
另请注意,文件大小定义为 UInt64
,但变量 sum
(保存到目前为止读取的字节总数)是一个 UInt32
。如果超过4GB的数据,这将导致问题。
但通常我会避免将完整数据读入内存缓冲区。您已经分块读取,因此您可以立即将数据写入目标文件。这是它的样子:
// Output file:
let fileURL = ...
let fileHandle = try FileHandle(forWritingTo: fileURL)
defer { fileHandle.closeFile() }
// Buffer:
let bufferSize = 1024 * 1024 // Choose some buffer size
var buffer = Data(count: bufferSize)
// Read/write loop:
let fileSize: UInt64 = file.size
var remainingToRead = fileSize
while remainingToRead > 0 {
let read = buffer.withUnsafeMutableBytes { bufferPointer in
self.sessionController.readFile(handle, data: bufferPointer, len: UInt32(min(remainingToRead, UInt64(bufferSize))))
}
if read == 0 {
return // Read error
}
remainingToRead -= UInt64(read)
fileHandle.write(buffer)
}
另请注意,数据直接读入 Data
值,而不是将其读入分配的内存,然后将其复制到另一个 Data
。
我正在使用第 3 方 SDK "sessionController" 从 MFi 外部设备将数据读取到缓冲区中。见下文:
let handle: UInt64 = self.sessionController.openFile(file.path, mode: openMode)
if handle == 0 {
//Error
return
}
let c: UInt64 = file.size
var bytesArray: [UInt8] = [UInt8](fileData)
let bufferPointer: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(c))
bufferPointer.initialize(repeating: 0, count: Int(c))
defer {
bufferPointer.deinitialize(count: Int(c))
bufferPointer.deallocate()
}
var sum: UInt32 = 0
let singleSize: UInt32 = 8 << 20
while sum < c {
let read = self.sessionController.readFile(handle, data: bufferPointer, len: singleSize)
if read == 0 {
//There was an error
return
}
sum += read
}
let newPointer : UnsafeRawPointer = UnsafeRawPointer(bufferPointer)
fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false).appendingPathComponent("test.MOV")
fileData = Data(bytes: newPointer, count: Int(c))
try! fileData.write(to: fileURL)
//Now use this fileURL to watch video in an AVPlayer...
//AVPlayer(init: fileURL)
由于某种原因,存储在 fileURL 的数据已损坏(我认为),我无法播放视频文件。我想我没有正确地使用 Unsafe Swift 做一些事情,但我不确定是什么。我怎样才能确保我已经正确地将数据从设备读取到内存中,然后从内存中取出该数据并将其存储在硬盘驱动器的 fileURL 中?我在这里做错了什么?给定 fileURL,视频将不会在 AVPlayer 中播放。
主要错误在这里:
let read = self.sessionController.readFile(handle, data: bufferPointer, len: singleSize)
如果您读取多个块,那么第二次和所有后续读取将覆盖 之前读取的数据。所以应该是
let read = self.sessionController.readFile(handle, data: bufferPointer + sum, len: singleSize)
另请注意,文件大小定义为 UInt64
,但变量 sum
(保存到目前为止读取的字节总数)是一个 UInt32
。如果超过4GB的数据,这将导致问题。
但通常我会避免将完整数据读入内存缓冲区。您已经分块读取,因此您可以立即将数据写入目标文件。这是它的样子:
// Output file:
let fileURL = ...
let fileHandle = try FileHandle(forWritingTo: fileURL)
defer { fileHandle.closeFile() }
// Buffer:
let bufferSize = 1024 * 1024 // Choose some buffer size
var buffer = Data(count: bufferSize)
// Read/write loop:
let fileSize: UInt64 = file.size
var remainingToRead = fileSize
while remainingToRead > 0 {
let read = buffer.withUnsafeMutableBytes { bufferPointer in
self.sessionController.readFile(handle, data: bufferPointer, len: UInt32(min(remainingToRead, UInt64(bufferSize))))
}
if read == 0 {
return // Read error
}
remainingToRead -= UInt64(read)
fileHandle.write(buffer)
}
另请注意,数据直接读入 Data
值,而不是将其读入分配的内存,然后将其复制到另一个 Data
。