iosswiftnsinputstreamnsfilehandlensoutputstream

Memory issue while converting big video file path to NSData. How to use InputStream/FileHandle to fix this issue?


I have a large sized video saved in my documents directory. I want to retrieve this video and remove it's first 5 bytes. For large video files of above 300 MB using [NSData(contentsOf: videoURL)] causing Memory issue error.

I have gone through Swift: Loading a large video file (over 700MB) into memory and found that we need to use [InputStream] and [OutputStream] or [NSFileHandle]for large files. How to use it?

Sample code is given below:

   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)")
   }

Solution

  • Solved this issue using InputStream/OutputStream.

    I have used InputStream to read the video, removed its first 5 bytes using dropFirst() method of Array and saved the new data using OutputStream.write().

    Sample code:

    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)
            })
        }