がりらぼ

WindowsRuntimeの応援ブログ

XNAでテキストファイルを読み込む

XNAで何かプロジェクトに追加したファイルを読み込もうとするとデフォルトではTextureやXml、WAVなど(あと3D関連)しか追加できません。テキストファイルなどはデフォルトでは読み込めないんですね。Xmlも指定フォーマットじゃないと読み込んでくれません。

XNAでは基本的にコンテンツパイプラインというものによってコンテンツが読み込まれます。
コンテンツインポーター(読み込み)→コンテンツプロセッサ(処理)→.xnbって感じに処理されます。
コンテンツプロセッサは読み込んだコンテンツに対しての処理を記述し、別になくても読み込めるので今回はほっといて、ファイルを読み込むのに重要なのがコンテンツインポータです。
テキストファイルなどデフォルトでサポートされていないファイルを読み込むにはContentsImporterクラスを継承したカスタムコンテンツインポータを自作しないといけません。
こいつが厄介でいかなるエラーが起ころうとfile not found(ファイルねぇよクソガ)としかエラーコードを返しません。(たぶん)
いつも悩むので一連の流れを書きます。

  • プロジェクトを作る

ソリューションから新しいプロジェクト→コンテンツ パイプライン拡張ライブラリを新規作成します。
取り合えすデフォルトで作成されるContentProcessor1.csは削除して、
追加→新しい項目→コンテンツインポーター を追加します。

  • カスタムコンテンツインポーターを作る
 [ContentImporter(".abc", DisplayName = "ABC Importer", DefaultProcessor = "AbcProcessor")]
    public class ContentImporter1 : ContentImporter<TImport>
    {
        public override TImport Import(string filename, ContentImporterContext context)
        {
            // TODO: 渡されたファイルをインポートする型のインスタンスに読み込みます。
            throw new NotImplementedException();
        }
    }

こんなのができたと思います。だいたい自動生成してくれます。
[ContentImporter(".abc"... のとこを好きな拡張子にしましょう。
Defaultプロセッサーは無くてもいいです。
どんな拡張子でもいい場合は[ContentImporter(DisplayName="ABCImporter")]だけでもOKです。
DisplayNameはコンテンツのプロパティで指定するときに必要です。好きな名前をつけましょう。

上のほうに

using TImport = System.String;

っていう行があると思いますのでそこを読み込みたい型に変えましょう。別にTImportをすべて変えてもOKです。今回はテキストファイルなのでstring型で行きます

ではthrowの行を削除してファイルを読み込んで指定した型をreturnする処理を記述しましょう。ファイルパスは引数のfilenameです。
テキストファイルを読み込む場合は以下となります。

[ContentImporter(DisplayName = "CustomText Importer")]
    public class ContentImporter1 : ContentImporter<string>
    {
        public override string Import(string filename, ContentImporterContext context)
        {
            return System.IO.File.ReadAllText(filename);
        }
    }

ここまで来たら一度プロジェクトをビルドしましょう。

  • 読み込む

では読み込みたいテキストファイルをソリューションのContentプロジェクトに追加しましょう。
Contentプロジェクトの参照に先ほど作成したコンテンツパイプラインのプロジェクトを追加します。
そしてファイルを右クリックでプロパティを開きます。
コンテンツインポータ欄を見ると自分が作成したインポータがあるはずです。それを選択します。
ビルドアクションはコンパイルのままにしてください。←ここがエラーの原因だったりします。

ではロードしてみましょう。

System.Diagnostics.Debug.WriteLine(this.Content.Load<string>("test"));


ちゃんと読み込めてますね(^q^)

  • 結論

XNAでファイルロードすんのめんどくさい。
ステージデータなどのファイルはあらかじめ作成してプロジェクトに追加し、読み込むことが個人的に多いのでちゃんとテキストファイルも読み込めると便利です。
コンテンツインポータをもっと拡張していろいろなファイルに対応できると便利ですね。

  • おまけ

file not foundで処理されるエラー一覧。(現在発見分)

  • ファイルパスが間違っている
  • 読み込む型が違うContent.Load("")←など
  • プロパティのビルドアクションが「コンパイル」以外になっている。確かどこかの情報ではコンパイルではダメとかだったような気がしますが僕の場合コンパイル以外だとエラーが出ます。