【问题标题】:Writing multiple NSData to File将多个 NSData 写入文件
【发布时间】:2011-10-26 14:21:06
【问题描述】:

我需要关于如何将多个 NSData 块写入单个文件的提示。使用 NSURLConnection 分块下载文件。每个块都在单独的 NSOperation 线程中下载。随着块完成下载,它们需要被写入文件,因此组合结果就是下载的文件。

管理返回的 NSData 并将其写入单个文件的最佳方法是什么?

【问题讨论】:

  • @Martin Gordon:我不认为这是重复的。它可能只是措辞使我不理解,但在我看来,他正在其他线程上下载离散块,然后必须重新创建文件。如果这是真的,那么在块进入时附加块将不起作用,因为文件不会正确排序(因为任何块都可能在任何其他块之前完成)。
  • 正如 Jason Cocoa 所说,每个文件块(任意大小)都在单独的线程中下载(因此在写入文件时调度可能是一个问题)。所有数据都需要合并到一个文件中。但由于文件的大小可能超过 100MB,因此数据被写入而不是保存在内存中很重要。

标签: objective-c cocoa


【解决方案1】:

不需要通过创建一个大的 NSMutableData 对象来消耗内存(无论如何,大下载是不可能的,因为你会耗尽内存),你也不需要浪费时间创建大量的小文件并连接它们(可能需要很长时间用大文件,iDevice磁盘IO不是很快)。

只需创建一个 NSFileHandle 并使用它将每个 NSData 对象写入到文件的末尾。

NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
[handle seekToEndOfFile];
[handle writeData:dataPiece];
[handle closeFile];

您需要先创建文件,以便您可以使用 NSFileHandle 打开它。为此,您可以使用以下内容编写第一个 NSData 片段,然后使用文件句柄编写其余部分。

[dataPiece writeToFile:filePath atomically:YES];

编辑:实际上我只是重新阅读了问题并意识到您正在使用单独的线程来下载块,因此它们可能无法按顺序完成,因此我的解决方案将不起作用。在我回答并跳过它的那一天,我一定很累。但是,希望我的回答至少可以帮助其他正在按顺序或单线程下载块的人。

【讨论】:

  • 有没有办法将数据写入文件内的特定位置?
  • 不要调用 seekToEndOfFile,而是寻找你想写的地方。
【解决方案2】:

将每个块写入单独的文件。然后在下载最后一个块时,以正确的顺序将每个文件连接成一个大文件。

【讨论】:

  • 您能否详细说明如何做到这一点。拥有多个文件后,如何将所有内容附加到单个文件?
  • 您可以使用 NSInputStream 和 initWithFileAtPath: 循环来一次读取一个小缓冲区(4 kb 是理想的),并使用 +[NSOutputStream outputStreamToFileAtPath:append:] 写入新文件。
【解决方案3】:

假设您知道最终的数据大小,并且您希望坚持使用 Foundation 类/Objective-C,您可以创建一个可以在这些操作之间共享的 NSMutableData 实例。当一个操作完成其块时,它应该锁定一些共享互斥体,将其完成的下载写入 NSMutableData 对象中的适当位置,然后解锁共享互斥体。

连接所有操作后,您可以使用 NSData 类上的 writeToFile: 便捷方法简单地将可变数据写入文件。如果您更精通 C/BSD,您还可以将文件创建为 mmap 并简单地写入。由于所有数据都将在映射中离散秒,因此您可以在不锁定互斥锁的情况下进行编写。加入所有操作后,您可以删除 mmap 并关闭文件。

【讨论】:

  • C/BSD 方法可能是一种方法,但我正在寻找 Objective-C 的答案。您提供的内容将起作用,但我担心文件大小并将其全部保存在内存中,直到完成下载。文件大小将超过 100MB。
  • @user326943:如果您担心文件大小,我认为 mmap 是要走的路。另一种选择是简单地打开文件句柄并查找/写入文件。此选项显然需要锁定,并且由于写入闪存设备的速度非常慢,因此在加入线程时可能会出现很多争用。
  • @user326943:另一个所有 Cocoa 选项可能是让操作写入一个临时文件,该文件命名为有意义的内容,例如主文件中的块序列。加入所有操作后,您可以将所有这些临时文件组合成最终的大文件,在单个线程上以块的形式读取和写入它们。
  • +1 表示mmap,请参阅stackoverflow.com/questions/9319874/… 以获得简单的实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-23
  • 2010-10-15
  • 1970-01-01
相关资源
最近更新 更多