圧縮文字列の展開
OpenSiv3Duser 2020/02/13(Thu) 23:28
ツールで圧縮データの文字列があります。展開方法を知りたいです。
XMLの読み込みに関しては成功しています。
<data></data>内の文字列の取得はできたとして、どうすればこの圧縮された文字列データを展開できるでしょうか?
下記ファイル desert.tmx
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" tiledversion="1.1.5" orientation="orthogonal" renderorder="right-down" width="40" height="40" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="desert.tsx"/>
<layer id="1" name="Ground" width="40" height="40">
<data encoding="base64" compression="zlib">
eJztmNkKwjAQRaN9cAPrAq5Yq3Xf6v9/nSM2VIbQJjEZR+nDwQZScrwztoORECLySBcIgZ7nc2y4KfyWDLx+Jb9nViNgDEwY+KioAXUgQN4+zpoCMwPmQAtoAx2CLFbA2oDEo9+hwG8DnIDtF/2K8ks086Tw2zH0uyMv7HcRr/6/EvvhnsPrsrxwX7rwU/0ODig/eV3mh3N1ld8eraWPaX6+64s9McesfrqcHfg1MpoifxcVEWjukyw+9AtFPl/I71pER3Of6j4bv7HI54s+MChhqLlPdZ/P3qMmFuo5h5NnTOhjM5tReN2yT51n5/v7J3F0vi46fk+ne7aX0i9l6If7mpufTX3f5wsqv9TAD2fJLT9VrTn7UeZnM5tR+v0LMQOHXwFnxe2/warGFRWf8QDjOLfP
</data>
</layer>
</map>
OpenSiv3Duser 2020/02/14(Fri) 00:49
公式のリファレンス場所です。
https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#data
説明が分かりにくいので要約すると、下記文字列を
eJztmNkKwjAQRaN9cAPrAq5Yq3Xf6v9/nSM2VIbQJjEZR+nDwQZScrwztoORECLySBcIgZ7nc2y4KfyWDLx+Jb9nViNgDEwY+KioAXUgQN4+zpoCMwPmQAtoAx2CLFbA2oDEo9+hwG8DnIDtF/2K8ks086Tw2zH0uyMv7HcRr/6/EvvhnsPrsrxwX7rwU/0ODig/eV3mh3N1ld8eraWPaX6+64s9McesfrqcHfg1MpoifxcVEWjukyw+9AtFPl/I71pER3Of6j4bv7HI54s+MChhqLlPdZ/P3qMmFuo5h5NnTOhjM5tReN2yT51n5/v7J3F0vi46fk+ne7aX0i9l6If7mpufTX3f5wsqv9TAD2fJLT9VrTn7UeZnM5tR+v0LMQOHXwFnxe2/warGFRWf8QDjOLfP
圧縮解凍した文字列データを取得したいです。OpenSiv3Dでその方法が知りたいです。
Reputeless 2020/02/14(Fri) 13:37
以下のコードで元データを得られます。
# include "zlib.h" // https://www.zlib.net/ (ヘッダのみ)
# include <Siv3D.hpp> // OpenSiv3D v0.4.2
void Main()
{
// zlib 圧縮 + Base64 エンコードされているデータ
const String base64 = U"eJztmNkKwjAQRaN9cAPrAq5Yq3Xf6v9/nSM2VIbQJjEZR+nDwQZScrwztoORECLySBcIgZ7nc2y4KfyWDLx+Jb9nViNgDEwY+KioAXUgQN4+zpoCMwPmQAtoAx2CLFbA2oDEo9+hwG8DnIDtF/2K8ks086Tw2zH0uyMv7HcRr/6/EvvhnsPrsrxwX7rwU/0ODig/eV3mh3N1ld8eraWPaX6+64s9McesfrqcHfg1MpoifxcVEWjukyw+9AtFPl/I71pER3Of6j4bv7HI54s+MChhqLlPdZ/P3qMmFuo5h5NnTOhjM5tReN2yT51n5/v7J3F0vi46fk+ne7aX0i9l6If7mpufTX3f5wsqv9TAD2fJLT9VrTn7UeZnM5tR+v0LMQOHXwFnxe2/warGFRWf8QDjOLfP";
// Base64 をデコードし、zlib 圧縮データを得る
const ByteArray src = Base64::Decode(base64);
const ::Byte* srcData = static_cast<const ::Byte*>(static_cast<const void*>(src.data()));
const size_t srcSize = src.size();
// 展開後のデータを保持できるサイズを用意。
// 小さすぎると uncompress に失敗。
uLong dstSize = 64 * 1024 ;
Array<s3d::Byte> dst(dstSize);
::Byte* dstData = static_cast<::Byte*>(static_cast<void*>(dst.data()));
// zlib 圧縮データを展開
const int result = ::uncompress(dstData, &dstSize, srcData, static_cast<uLong>(srcSize));
if (result == Z_OK)
{
Print << U"展開に成功 ({} bytes)"_fmt(dstSize);
dst.resize(dstSize);
const size_t uintCount = dst.size() / sizeof(uint32);
// Array<uint32> にコピー
Array<uint32> data(uintCount);
std::memcpy(data.data(), dst.data(), dst.size_bytes());
Console << data;
}
else
{
Print << U"展開に失敗";
}
while (System::Update())
{
}
}
OpenSiv3Duser 2020/02/14(Fri) 23:26
Zlibサイトから、ライブラリファイルをDLして、
ヘッダーファイルのネストインクルードも考えて、
とりあえず、〜.h は全部突っ込んだところ、サンプルが動作しました。
ありがとうございます。
出力データのデフォルトが圧縮文字列になっており、なるだけ直感的に何もいじらずにできるようにしたいと考えています。
便利さを追求すると手間がかかりますが、サポートとか考えると、後の楽を取れるのでいいかと考えて行っています。
Visual Studio 2019 Community(最新バージョン) を使っていますが、途中、ヘッダーファイルがらみの未定義エラーが出てビルドエラー、しかし実行されるという、実行は動作的に何も問題が起きないという、VisualStudioの怪現象にハマりました。
ソリューションのクリアや中間ファイルの削除やその他いろいろやりましたが、この謎現象は直らず、
ひょっとして後からヘッダーファイルを突っ込んでバグったかと思い、
あきらめて新規で、先にヘッダーファイルを先に入れてから作成したら、こちらはおかしな挙動は全くしません。
(※ヘッダーがらみの情報の紐づけがVisualStudioがバグったと思ったため)
VisualStudioはヘッダーファイルがらみは先にしっかり行わないと、インテリセンスなど挙動がおかしくなる可能性があるようです。
OpenSiv3DライブラリやZlibはもちろん、問題はありません。
話は変わりますが、画像認証の数字入力ですが、
例えば、見やすいんだけど巡回ロボットには認識できない文字列、
"6 plus 3 plus 7" とかの簡単な計算式の文字、
もしくは漢数字や麻雀ハイを使うとかは可能でしょうか?
入力の際によく間違えてしまうので、もし可能ならば検討いただきたいです。