2017-01-15 4 views
0

Swift/iOSでファイルをマージする方法はありますか? FileManagerはアイテムを移動してコピーすることができますが、ファイルのマージについては何も見ていません。私は、ファイルが潜在的に大きなものとなりますので、私はむしろ、メモリ内にデータを渡すことを避けるだろうSwift - merge files

FileManager.default.merge(files: [URL], to location: URL) throws

ようなものを持っているしたいと思います。ここ

===メモリマージに私自身である:ここでは

let data = NSMutableData() 
files.forEach({ partLocation in 
    guard let partData = NSData(contentsOf: partLocation) else { return } 
    data.append(partData as Data) 
    do { 
    try FileManager.default.removeItem(at: partLocation) 
    } catch { 
    print("error \(error)") 
    } 
}) 
data.write(to: destination, atomically: true) 
+1

料理のオプションが常にありますあなた自身の。宛先への書き込み中に連続して各ファイルから読み込みます。 – Alexander

+1

"目的地に追加する"のようなものはありますか?可能であれば、私はファイル全体を読んだり、メモリ使用量を制限するように書いてはいけません。 – Guig

+1

そのため、あなたは 'FileHandle.readData(ofLength:Int)'を持っています。あなたは4kbのチャンクのようなものを読んでループにして、それらを出力に書き出すことができます。バッファを大きくすると、カーネルのコンテキスト切り替えのオーバーヘッドを最小限に抑えることでパフォーマンスが向上しますが、メモリを増やすことになります – Alexander

答えて

1

は(指導に感謝@Alexander)私自身のソリューションです

extension FileManager { 
    func merge(files: [URL], to destination: URL, chunkSize: Int = 1000000) throws { 
    try FileManager.default.createFile(atPath: destination.path, contents: nil, attributes: nil) 
    let writer = try FileHandle(forWritingTo: destination) 
    try files.forEach({ partLocation in 
     let reader = try FileHandle(forReadingFrom: partLocation) 
     var data = reader.readData(ofLength: chunkSize) 
     while data.count > 0 { 
     writer.write(data) 
     data = reader.readData(ofLength: chunkSize) 
     } 
     reader.closeFile() 
    }) 
    writer.closeFile() 
    } 
} 
+0

マージがうまくいきました。大きなファイルをマージしているときにメモリの問題をどう処理するか考えていますか? – sujay

+0

chunkSizeは、使用されるメモリの量を制御します。 – Guig

+0

と、大きなファイルをマージするときに、どのようにクリアすることができますか? – sujay

0
func merge(files: [URL], to destination: URL, chunkSize: Int = 100000000) { 
     for partLocation in files { 
      // create a stream that reads the data above 
      let stream: InputStream 
      stream = InputStream.init(url: partLocation)! 
      // begin reading 
      stream.open() 
      let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: chunkSize) 
      //   var writeData : Data = Data() 
      while stream.hasBytesAvailable { 
       let read = stream.read(buffer, maxLength: chunkSize) 

       var writeData:Data = Data() 
       writeData.append(buffer, count: read) enter code here 
       if let outputStream = OutputStream(url: destination, append: true) { 
        outputStream.open() 
        writeData.withUnsafeBytes { outputStream.write($0, maxLength: writeData.count) } 
        outputStream.close() 
        writeData.removeAll() 
       } 
      } 
      stream.close() 
      buffer.deallocate(capacity: chunkSize) 

     } 
    }