エンジニア

C#のLINQでcocos2d-xのmanifestファイルを集計する

投稿日:2020年12月17日 更新日:

今回のDevelopers' Blogを担当する加賀です。
ちょっとした小ネタ記事を書いてみました。

cocos2d-xには、外部リソースファイルのダウンロード管理を行うAssetsManagerExという機能があります。
AssetsManagerExは、JSON形式で記述されたmanifestファイルでダウンロードするファイルの一覧を管理します。

先日、ダウンロードするファイルの種類ごとに、ファイルの数とサイズの合計を集計する事になり、
すぐにそれを行えるツールがなかったため、C#を使って自作することにしました。

C#でJSONを読み込むためにNewtonsoft.Jsonを使用し、集計にLINQを使用します。
Newtonsoft.JsonのLINQ機能は、Newtonsoft.Json.Linq名前空間に存在します。
今回使用したバージョンは、.NET Framework 4.8、Newtonsoft.Json 12.0.3 です。

cocos2d-xのmanifestファイル構造

manifestファイルは以下のような構造になっています。

{
    "remoteManifestUrl": "https://www.example.com/example.manifest",
    "version": "123",
    "assets": {
        "(ファイルパス)": {
            "md5": "0123456789abcdef0123456789abcdef",
            "size": 123456
        },
        "(ファイルパス)": {
            "md5": "fedcba9876543210fedcba9876543210",
            "size": 1234
        },
        ...
    }
}

JSONを集計する

ファイルは用途別にディレクトリに分けて設置されているため、
ディレクトリごとにファイルの数とサイズの合計を集計します。
なお、manifestファイルの構造は正しいものとして扱い、エラー制御は省略しています。

using System;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;

class Program
{
  static void Main(string[] args) {
    var json = JObject.Parse(File.ReadAllText("example.manifest"));
    // ファイル一覧部分を取り出す
    var assets = json["assets"];

    // 使用目的別のファイル数と合計ファイルサイズを集計する
    var result = assets
    // LINQメソッドを使えるようにする
      .AsJEnumerable()
    // Key:Valueを表すJPropertyにキャスト
      .Cast<JProperty>()
    // 使用目的別(ディレクトリ別)のリストにする
    // Value側もオブジェクト形式にキャストする
      .GroupBy(p => p.Name.Contains('/') ? p.Name.Substring(0, p.Name.LastIndexOf('/')) : "/", p => p.Value as JObject)
    // 各使用目的ごとにファイル数と合計ファイルサイズを集計する
      .Select(g => g
        .Aggregate(
          new { g.Key, num = 0, size = 0L },
          (ret, obj) => new { ret.Key, num = ret.num + 1, size = ret.size + obj["size"].Value<long>() }
        )
      )
      .ToList();

    // 結果出力
    result.ForEach(ret => Console.WriteLine($"{ret.Key}    num: {ret.num}    size: {ret.size}"));
  }
}

出力例は以下の様になります。

/    num: 2    size: 1024
audio/se    num: 10    size: 123456
audio/bgm    num: 4    size: 1234567
banner    num: 32    size: 123456789
最後に

JSONは、子要素に値以外の配列やオブジェクトを持つことができます。
そのため、基底クラスのJTokenで取得するメソッドが多く、キャストを書くことが多くなるのが難点ではあります。

このような情報は手作業で集計することも出来ますが、非常に手間がかかります。
このプログラムを使うことで、欲しい情報を小さなコストで繰り返し得ることができ、
もともと行いたかったファイルダウンロード処理の改善コストの削減にも繋がりました。
こういった「小さいけど大きく役立つプログラム」をこれからも書いていこうと思います。

採用情報

ワンダープラネットでは、一緒に働く仲間を幅広い職種で募集しております。

-エンジニア
-

© WonderPlanet Inc.