"行の読み込み"のそれぞれ
プログラムを作成するにあたって、ファイルからテキストを一行ずつ読み込んで処理をするっていうのは、HelloWorldの次にやることなんですが、Cocoa(Objctive-C)でこれをやろうとして結構面倒なことに気がつきました。Cocoaではいくつアプリケーションを作成しているのですが、これまで"テキストを一行ずつ読み込んで"処理をするという場面には出くわさなかったんですね。例えば、C++(STD)では
ifstream inf("/path/to/sample.txt",ios::in);
vector<string> lines;
string line;
while(getline(inf,line)) { lines.push_back(line); }
inf.close();
#ifdef _DEBUG
vector<string>::iterator itr;
for(itr=lines.begin();itr!=lines.end();itr++)
{
cout << itr->c_str() << endl;
}
#endifMFCでも似たようなもので
CStdioFile inf("C:/path/to/sample.txt",CFile::modeRead);
CStringArray lines;
CString line;
while(inf.ReadString(line)) { lines.Add(line); }
inf.Close();
#ifdef _DEBUG
INT_PTR c = lines.GetCount();
for(unsigned int i=0; i<c; i++)
{
cout << (LPCSTR)lines.GetAt(i) << endl;
}
#endif見た目は、ほぼ同じ。違いはC++(STD)では、stringクラスの定義にgetline()がグローバル関数として定義されているのに大してMFCのそれはCStdioFileクラスに定義されているってことくらい。"一行ずつ読む"ってことを文字の固まり(=string)に抽象化するのか、ファイルに抽象化するのか?このあたりが設計思想の違いなのでしょう。僕としては、文字の固まりに抽象化する方がより自由度が高いかなぁなんて感じてますが...で、肝心のCocoa(Objective-C)はというとC++(STD)に近くNSStringクラスにありました。よりオブジェクト指向らしくNSStringのインスタンスメソッドとしてgetLineStart:end:contentsEnd:forRange:が用意されていました。
NSError* err;
NSString* rdata = [NSString stringWithContentsOfFile:@"/path/to/sample.txt"
encoding:NSUTF8StringEncoding error:&err];
NSRange range;
NSMutableArray* lines = [[[NSMutableArray alloc] init] autorelease];
unsigned int lineStart,lineEnd,contentsEnd,readLength;
lineStart = 0; lineEnd = 0; readLength = 0;
while(lineEnd < [rdata length])
{
range = NSMakeRange(lineEnd,0);
[rdata getLineStart:&lineStart end:&lineEnd contentsEnd:&contentsEnd
forRange:range];
readLength = contentsEnd - lineStart;
[lines addObject:
[rdata substringWithRange:NSMakeRange(lineStart,readLength)]];
}
#ifdef _DEBUG
NSEnumerator* enumerator = [lines objectEnumerator];
NSString* line;
while((line = [enumerator nextObject]))
{
NSLog(@"%@",line);
}
#endifまあ、コードが長くなるのは仕方がないにせよファイルカーソル位置を自分で調整しながら読込みをするのはやっぱりバギーな気がしますね。やっぱ、while((line = [rdata getLine])) ... みたいなのがいいな。
もっと別の解があるのじゃないかと悩んだりもしますが一応やりたいことはできたのでこれ以上突っ込んでいません。Objective-Cの強みは、最後はCで書けるっていう強みもありますし。(一行が長〜いという心配はありますけど)perlやらrubyな人には関係ないですね。Cocoa(Objective-C)の構文はオブジェクト指向っぽいという意味では一番好きなんですが、やっぱタイプ量は少ない方がいいかなと思ったりもします。
char c_line[256];
FILE* fp = fopen("/path/to/sample.txt","r");
while(fgets(c_line,sizeof(c_line),fp))
{
memset(c_line,0x00,sizeof(c_line));
[lines addObject:[NSString stringWithCString:c_line
encoding:NSUTF8StringEncoding]];
}
fclose(fp);
#ifdef _DEBUG
NSEnumerator* enumerator = [lines objectEnumerator];
while((line = [enumerator nextObject]))
{
NSLog(@"%@",line);
}
#endif






最近のコメント
34 weeks 5 days ago
51 weeks 5 days ago
51 weeks 5 days ago
1年 16 weeks ago
1年 16 weeks ago
1年 17 weeks ago
1年 28 weeks ago
1年 28 weeks ago
2 years 8 weeks ago
2 years 17 weeks ago