編集:
このサイズのファイルを処理する場合、巨大な入力ファイルもほぼ巨大な出力ファイルも、一度に数メガバイトのファイル全体をメモリにロードしたくない場合があります。これをストリーミング方式で解析しfoundCharacters
、メモリに重要な部分を保持せずに、進行中にデータをデコードする必要があります。
ただし、従来の手法では、プロセスの3つのフェーズでXMLファイルメモリ全体を保持できます。
サーバーからXMLファイルをダウンロードすると、
XMLパーサーがそのファイルを解析するとき。と
Base64を実行すると、ファイルがデコードされます。
秘訣は、単一の大きなXMLファイルの小さなチャンクに対して、これら3つのプロセスを同時に実行するストリーミング手法を採用することです。結論として、50 MBのファイル全体をダウンロードするときに、数kbを取得し、XMLを解析します。また、Base64でエンコードされたフィールドを解析する場合は、その数kbに対してBase64デコードを実行し、次の手順に進みます。データのチャンク。
この例(少なくとも、Base64デコードを含まないストリーミングXMLのダウンロードと解析)については、AppleのXMLPerformanceサンプルプロジェクトを参照してください。NSXMLParser
よく知られている2つのXMLパーサーと、あまり馴染みのないパーサーが示されていることがわかりますLibXML
。の問題NSXMLParser
は、それ自体のデバイスに任せて、を使用している場合でも、解析を開始する前にXMLファイル全体をメモリにロードすることですinitWithContentsOfURL
。
initWithContentsOfURL
以前の回答では、を使用すると、NSXMLParser
ダウンロード中にURLの内容が小さなパケットに解析されると誤って主張しました。プロトコルのfoundCharacters
方法は、方法NSXMLParserDelegate
と非常に類似しているように思われるので、ダウンロードの進行中に情報を返すという、同じようにストリームを処理することになると確信していました。悲しいことに、そうではありません。NSURLConnectionDelegate
didReceiveData
NSXMLParser
NSURLConnection
ただし、Apple XMLPerformanceサンプルプロジェクトのように、を使用LibXML
することで、実際NSURLConnection
にストリーミング機能を使用して、その場でXMLを解析できます。
私は小さなテストプロジェクトを作成しましたが、AppleのXMLPerformanceサンプルプロジェクトを詳細に確認することをお勧めします。しかし、私の実験では、56MBのXMLファイルは解析と変換の際に100MBをはるかに超えて消費しNSXMLParser
ましたが、を使用した場合は2MBしか消費しませんでしたLibXML2
。
コメントでは、Base64でエンコードされたデータをファイルにダウンロードしてからデコードしたいという要望を説明しています。そのアプローチははるかに効率が悪いように見えますが、確かに機能する可能性があります。ちなみに、その最初のダウンロードでは、同じメモリの問題があります(上記で解決しました)。Base64でエンコードされたデータを最初にダウンロードしても、ほとんどのルーチンのようにRAMに簡単にロードされないようにすることをお勧めします。を使用していると仮定して、RAMに保持するのではなく、でデータを受信するときにNSURLConnection
データをに書き込みます。NSOutputStream
didReceiveData
(これらのルーチンのほとんどは、適度なサイズのファイルを処理していると想定しているため)にファイルを追加する一般的なパターンではなく、受信時にファイルを書き込む方法の例については、didReceiveResponse
AppleのAdvancedURLConnectionsの例のAdvancedGetController.mを参照してください。 NSMutableData
)。(認証などに関するAdvancedURLConnectionsサンプルのすべてのものを無視しますが、それがどのように書き込まれるかを理解することに焦点を当てますNSOutputStream
。)この手法は、この回答の上部にリストされている3つの問題の最初の問題に対処しますが、後者の2つ。そのためにはLibXML2
、AppleのXMLPerformanceサンプルプロジェクトに示されているように、または他の同様の手法を使用することを検討する必要があります。