ページ

2015年4月10日金曜日

cocos2d-xでテキストファイルを1行ずつ処理する方法

cocos2d-xでキャラクターのセリフなどをテキストファイルから読み込んで、1行ずつ処理するにはどうしたらよいのかを検討してみたのでメモ。

バージョン


cocos2d-x v3.5

結論


先に結論を書くと、

FileUtilsのgetStringFromFile()メソッドでテキストファイルを読み込み、改行文字で分割して処理する

です。

経緯


この方法は最初に思いついた方法です。

しかし、C++の標準ライブラリには文字列を分割するAPIがないため、自分で実装するか、外部のライブラリを使用する必要があります。

それはちょっと面倒臭い上に、あまりスマートではない気がしたので、ファイルを1行ずつ読み込んで処理する方法がないかを模索したところ、std::ifstreamを使えばいけるのではと考えました。

コードはこんな感じです。

#include <fstream>

USING_NS_CC;

auto filePath = FileUtils::getInstance()->fullPathForFilename("sample.txt");

std::ifstream inFile(filePath);
for (std::string line; std::getline(inFile, line);) {
    // ここに処理を記述
    log("%s", line.c_str());
}

この例ではResourcesディレクトリ直下に「sample.txt」を配置しているという想定です。

FileUtilsのfullPathForFilename()メソッドでパスの問題を解決し、std::ifstreamでファイルを開きます。

そして、std::getlineで1行ずつ読み込んでいます。

これでちゃんと動作したので、よっしゃ!と思ったのですが、問題が起こりました。

上記のコードは、iOSとWin32では問題なく動くのですが、Androidでは動かなかったのです。

問題は以下の部分です。

std::ifstream inFile(filePath);

Androidではここでファイルを開くことが出来ませんでした。

調べた所、Androidの場合、リソースファイルはapkファイルにzip形式で格納されますが、std::ifstreamはzipに格納されたファイルを読み込むことが出来ない、というのがその理由でした。

というわけで、残念ですがstd::ifstreamを使った方法は断念し、最初の案を採用することにしたのでした。

コード例


文字列を分割する方法は色々あるようですが、こちらの方法が短く書けていいかなと思いました。


これを使って書くと、こんな感じです。

USING_NS_CC;

auto split = [](const std::string& input, char delimiter) {
    std::istringstream stream(input);
    std::string field;
    std::vector result;
    while (std::getline(stream, field, delimiter)) {
        result.push_back(field);
    }
    return result;
};

auto fileText = FileUtils::getInstance()->getStringFromFile("sample.txt");
auto lines = split(fileText, '\n');
for (const auto& line : lines) {
    // ここに処理を記述
    log("%s", line.c_str());
}

にしても、何か他に良い方法はないものだろうか…。

参考リンク


0 件のコメント:

コメントを投稿