本ブログシリーズは、毎週AlteryxのTipsをお伝えしていく週刊AlteryxTipsブログです。
Alteryxは基本的に構造化データを扱うソフトウェアです。しかしながら、Blob入力ツールというツールを使えば、バイナリを読み込むことも可能です。今回はAlteryxでバイナリファイルを扱う方法について解説します。
Alteryxでバイナリデータを扱う方法
Alteryx Designerでバイナリを扱うにはいくつかの方法があります。
- 外部のソフトウェアをコマンド実行ツールで起動させ、テキスト形式などに変換する
- Pythonツールを使ってPythonでテキストに変換する
- Blob入力ツール/Blob変換ツールを駆使する
1番目の方法は、測定機器などでバイナリ形式で測定結果を保存するような場合に、専用の変換ソフトが提供されることがあります。これをコマンド実行ツールでコマンドラインで起動させてCSV形式などに変換する方法です。この方法でAlteryxのデータ処理パイプランに組み込むことが可能です。提供されている専用ツールがコマンド実行でファイル出力までできない場合は、別の手段を講じる必要があります。
2番目の方法は、Pythonで提供されているライブラリを使ってCSVなどに変換する、という方法です。ライブラリさえ提供されていれば、なんとかなるはずです(コードを書かないといけないですが)。
3番目はいわゆるBaseA(Alteryxの基本ツールだけでどうにかすること)になりますが、基本的にバイナリ処理は早くないのと、バイナリファイルの解析は結構大変なので、おすすめはできないのですが、とはいえこれでなんとかしたい、という方のために今回はこの方法について解説をしていきたいと思います。
ちなみに、取り扱うファイルが画像ファイルで、それを単なる画像として取り扱いをしたい場合は簡単です。Blob変換ツールですぐに画像化できます。
例:ZIPファイルを直接読み込み中に格納されているファイル名を取得する
今回は、例としてZIPファイルをBlob入力ツールで読み込み、格納されているファイルが何であるか、というのをAlteryxだけでやってみたいと思います(さすがにファイルの展開は複雑なので今回はやりません)。
ファイル名が含まれているところを抽出するには?
この作業を行う場合、バイナリファイルのフォーマットを知る必要があります。著名なフォーマットであればインターネット上で何かしらドキュメントが見つかるはずです。今回はWikipediaに簡単な説明があったので、これとインターネット上で検索して発見したZIPフォーマットを解析した方のブログなどを参考にしています。
ちなみに、ファイル名が含まれている部分は、「セントラルディレクトリ」という部分にまとまっているので、ここを読めばファイル名は入手可能です。構造的には、以下のようになっています(世界一雑な説明ですね・・・)。

このセントラルディレクトリですが、スタートは16進表記で「504B0102」で始まります。そのため、バイナリデータを16進に変換すれば場所の特定が可能です。
バイナリファイルを読み込み、16進数に変換する
このためには、開発者カテゴリにあるBlob入力ツールとBlob変換ツールを使います。

Blob入力ツールは単に読み込みを行うだけです。

Blob変換ツールでは、「Blobフィールドから変換する」を選択し、「HEXでエンコードされたバイナリデータに変換する」を選択します。

これにより、結果ウィンドウでバイト表記されていたものが、16進数の英数字表記に変換できます。

ここまでくれば、あとはいつもの正規表現ツールなどを駆使してほしい部分を抽出していくことになります。
セントラルディレクトリエントリを抽出する
みんなだいすき正規表現ツールを使いましょう。実は、セントラルディレクトリエントリの後ろにコメントなどが入る部分があるので、504B0102から最後までを取得してはだめです。504B0506の直前までを取得します。
使う正規表現は以下のようになります。出力方法は「解析」です。

(504B0102.*)504B0506
ただし、このセントラルディレクトリエントリ部分には、格納しているファイル一個ずつに存在するため、実際の中身は以下のような構造になっています。

このそれぞれの数値の部分が「504B0102」で開始されるため、さらに個別の行にわけていきます。これも正規表現ツールを使います。

504B0102.*?(?=504B0102|$)
これで以下のように取得できました。

このような「頭が特定の文字列で始まった部分を連続的に抽出する」場合、今回のケースだと「504B0102.*?」という正規表現で取れそうですが、これを行うと、「504B0102」のみが行に分かれてきます。ですので、後読みを使った上記のような正規表現分を使う必要があります。ちなみに、最後の方にある「|$」を使うことで、ラストのパターンも抽出できるようにしています。これをつけないと最後の1パターンが取得できません。「|」は「もしくは」で、「$」は行末を意味します。
セントラルディレクトリエントリの各要素を抽出する
ここからはファイルフォーマットとのにらめっこです。ここでも正規表現ツールを使っています。欲しいところが決まっていればそこだけフォーミュラツールの関数で切り出すことも可能ですが、ここではなるべくちゃんと整形するようにしています。

固定長の部分は、基本的に決まった文字数で切り出すだけなので、このような単純(だけどもめんどくさい)方法で抽出が可能です。ただし、セントラルディレクトリエントリの後半部分(ファイル名以降)は可変長で構成されているので、固定長の部分に記載されている場所を頼りにフォーミュラツールで切り出していく必要があります。ちなみに、Wikipediaに記載のフォーマットは以下のとおりですが、サイズと記載された項目の文字数の二倍の文字数を正規表現ツールでは指定する必要があります(2文字で1セットなので)。

基本的にはファイル名の長さ(FileNameLength)の部分に数値が記載されているので、この値を使います。

ファイル名部分を切り出す
このファイル名の長さですが、1000とか1B00とか記載されていますが、1000は10進数では4096です。しかしどう見てもそんな大量の文字が入っているように見えません。
正解としては、16文字です。これは、リトルインディアン表記なので「1000」は「0010」として10進数に変換する必要があります(2文字1セットで、後ろから表記されている、ということです)。
実際にファイル名を切り出すために以下のような計算をしています。可変長部分は「RegExOut18」に格納されているので、左からファイル名の長さ分の文字数を切り出せばオッケーです。

文字に変換する
最後に文字列に変換しましょう。これには一度Blob変換ツールでバイナリに戻してからさらにBlob変換ツールでエンコード方式を指定して文字に変換可能です。
まずバイナリに変換します。16進数で表記されているFileNameフィールドを指定し、「フィールドはHEXエンコードされたバイナリデータである」を選択します。

これでバイナリになります。
次に、エンコードを指定して文字列に戻します。このためにはエンコード方式を指定する必要があります。基本的にはZIPファイルはIBM PCのエンコード方式にしか対応していませんが、今では拡張されており、UTF-8で格納することができます。UTF-8になっているかどうかは、汎用目的のビットフラグ(BitFlagもしくは仕様書上ではgeneral purpose bit flagという項目)に格納されています。
今回のファイルは英数字で構成されているファイルでしたが、この項目は「0800」となっており、リトルインディアンを考慮すると、16進表記で「0080」なのでこれを2進数にすると「1000」となり3ビット目のみ1が立っているため、UTF-8は使われていないということになります。
ちなみに、WindowsのExplorerで日本語名のファイルをZIPファイルをで圧縮すると、「0808」となり、2進数だと「100000001000」となり、UTF-8のビット(11ビット目)に1が立ちます。
実際のやり方としては、以下のようにBlob変換ツールで、「BLOBはあるコードページでエンコードされたテキストである」を選択し、適した文字コードを選ぶだけです。今回は英数字の基本的なフォーマットなので「ISO 8859-1 Latin 1」にしています。

これで以下のようにファイル名に変換できました。

全体的なワークフローは以下のようになります。

まとめ
- Alteryxでバイナリファイルを扱う方法をご紹介しました
- 扱うバイナリファイルのフォーマットがわかっていればAlteryx内の基本ツールだけでも処理することは可能です(が、大きいファイルはおそらく処理に時間がかかりますし、可変部分が多いと正直大変)
- Pythonのライブラリが提供されていれば、そちらのほうが手っ取り早いです
サンプルワークフローダウンロード
次回
今回、とうとう100という区切りに達しました。この100回をもって一旦週刊から不定期更新にしたいと思います。2年間お付き合いくださりありがとうございました!
コメント