このようなテキストファイル my.txt があるとします
this is line 1
this is line 2
....
this is line 999999
this is line 1000000
Unix では、「head -1000 my.txt | tail -1」のようなコマンドを発行すると、「this is line 1000」という行を取得できます。Objective-Cでこれを取得する対応する方法は何ですか?
このようなテキストファイル my.txt があるとします
this is line 1
this is line 2
....
this is line 999999
this is line 1000000
Unix では、「head -1000 my.txt | tail -1」のようなコマンドを発行すると、「this is line 1000」という行を取得できます。Objective-Cでこれを取得する対応する方法は何ですか?
すべてを一度にメモリに保存するのが非効率的でない場合、最もコンパクトな一連の呼び出し(簡単な説明のために複数の行に拡張しました)は次のようになります。
NSError *error = nil;
NSString *sourceString = [NSString stringWithContentsOfFile:@"..."
encoding:NSUTF8StringEncoding error:&error];
NSArray *lines = [sourceString componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
NSString *relevantLine = [lines objectAtIndex:1000];
の値error
とcount
の値を確認lines
して検証する必要があります。
編集:ネイサンの答えと比較するために、セット内の文字で分割することの利点は、改行を区切る可能性のある5つのUnicode文字のいずれかを受け入れることです。 1回の休憩(例:)\r\n
。
NSInputStream
メモリフットプリントが問題である場合、おそらくこれに対処する必要があります。これは、Cのstdio.h fopen / fread / etcよりもほとんど進化していないため、ダッシュスルーするために独自の小さなループを作成する必要があります。 。
答えは、大きすぎてメモリに保持できないファイルを読み取る方法を説明していません。Objective-C には、大きなテキスト ファイルをメモリに格納せずに読み取るための優れたソリューションはありません (これは常にオプションとは限りません)。
これらの場合、私は c メソッドを使用するのが好きです:
FILE* file = fopen("path to my file", "r");
size_t length;
char *cLine = fgetln(file,&length);
while (length>0) {
char str[length+1];
strncpy(str, cLine, length);
str[length] = '\0';
NSString *line = [NSString stringWithFormat:@"%s",str];
% Do what you want here.
cLine = fgetln(file,&length);
}
fgetln は改行文字を保持しないことに注意してください。また、NULL 終端のためのスペースを作りたいので、str の長さを +1 します。
最も簡単な方法は、NSStringファイルメソッドの1つを使用してファイルをロードしてから、-[NSString componentsSeparatedByString:]メソッドを使用してすべての行の配列を取得することです。
または、NSScannerを使用して、改行/キャリッジリターン文字をスキャンし、目的の行に到達するまでそれらをカウントすることもできます。
メモリ使用量が本当に心配な場合は、NSInputStreamを使用してファイルを読み込み、改行の数を数えます。NSScannerがNSInputStreamで動作しないのは残念です。
ファイル内のいくつかの行をスキップしたいように聞こえるので、これは正確な複製ではないと思いますが、次のようなアプローチを簡単に使用できます。
Objective-C: ファイルを 1 行ずつ読み取る (サンプル コードを含む特定の回答)
入力ファイルをループし、データのチャンクを読み取り、改行を探します。それらを数えて、正しい数字にヒットしたら、その数字から次の数字までのデータを出力します。
あなたの例は数十万行あるように見えるので、ファイルをNSStringに読み込むだけでなく、NSArrayに変換しないでください。
より洗練された NSInputStream の方法 (文字セットのデコードにいくつかの重要な利点があります) を使用したい場合は、ストリーム ソースからすべてのデータを消費するためのポーリングの基本的な考え方を示す素晴らしい例を次に示します (ファイルの例では、そのやややり過ぎ)。これは出力用ですが、アイデアは入力にも適しています: ポーリングと実行ループのスケジューリング