【问题标题】:Memory issue while converting big video file path to NSData. How to use InputStream/FileHandle to fix this issue?将大视频文件路径转换为 ​​NSData 时出现内存问题。如何使用 InputStream/FileHandle 来解决这个问题?
【发布时间】:2020-01-23 12:06:04
【问题描述】:

我的文档目录中保存了一个大型视频。我想检索这个视频并删除它的前 5 个字节。 对于超过 300 MB 的大型视频文件,使用 [NSData(contentsOf: videoURL)] 会导致内存问题错误。

我已经通过Swift: Loading a large video file (over 700MB) into memory 发现对于大文件我们需要使用[InputStream]和[OutputStream]或者[NSFileHandle]。如何使用它?

示例代码如下:

   let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
   let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
   let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
   if let dirPath = paths.first{
      let videoURL = URL(fileURLWithPath: dirPath).appendingPathComponent(filePath)
          do {
                let videoData = try NSData(contentsOf: videoURL)
                let mutabledata = videoData.mutableCopy() as! NSMutableData
                mutabledata.replaceBytes(in: NSRange(location: 0, length: 5), withBytes: nil, length: 0)
   }catch {
       print("Error Writing video: \(error)")
   }

【问题讨论】:

  • 如果要替换 5 个字节,可能会浪费读取整个文件。或许你可以使用FileHandler的函数如seekwrite
  • @netigger 谢谢!如何写入 FileHandler 来做同样的事情?
  • @netigger 是否已弃用?
  • 哦,我没注意到:|

标签: ios swift nsinputstream nsfilehandle nsoutputstream


【解决方案1】:

这适用于我更改前 4 个字节,并且我没有收到弃用警告。

let input = FileHandle(forWritingAtPath: "/tmp/test.in")!
input.write("12345".data(using: .utf8)!)

【讨论】:

  • 这个文件大小是实际的文件 data.count 吗?如果是这样,这会导致我的应用在 input.read(pointer, maxLength: filesize - toSkip) 处崩溃(内存问题)
  • 这会将特定数据写入接收器,对吗? @netigger
  • 是的,首先替换那里的任何东西
  • 读取 EOF 导致 400 MB 视频崩溃。
  • 你到底在做什么?我试过自己更改 400MB 文件的前 5 个字节,效果很好。
【解决方案2】:

使用 InputStream/OutputStream 解决了这个问题。

我使用 InputStream 读取视频,使用 Array 的 dropFirst() 方法删除了它的前 5 个字节,并使用 OutputStream.write() 保存了新数据。

示例代码:

func read(stream : InpuStream){
        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: totalLength)
        while stream.hasBytesAvailable {
            let length = self.inputStream.read(buffer, maxLength: totalLength)
            if(length == totalLength){
                let array = Array(UnsafeBufferPointer(start: buffer, count: totalLength))
                var newArray: [UInt8] = []
                newArray = [UInt8](array.dropFirst(5))
            }
    }
    func write(){
        let data = Data(_: newArray)
        data.withUnsafeBytes({ (rawBufferPointer: UnsafeRawBufferPointer) -> Int in
            let bufferPointer = rawBufferPointer.bindMemory(to: UInt8.self)
            return self.outputStream.write(bufferPointer.baseAddress!, maxLength: data.count)
        })
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多