Winシステム Winフォーマットの処理の仕方


スポンサーリンク

Winシステムは、地震波形を取り扱うシステムです。
そのシステム内で用いられるファイル書式がWinフォーマットというわけだ。

ところがこのWinフォーマットの設計がゴミ。
記録速度を考慮してのことなどと言い訳しているが実際に処理するときに構造化しにくい。
なのでWinフォーマットは、自身の処理しやすいファイル形式に変換して保存するのが吉なのかも。

それはおいといて、学生さんとか新規プロジェクトで見積もりとかしないといけなかったりするので、
Winフォーマットの処理の仕方を書き残しておくことにします。

Winフォーマット



Winファイルは、ヘッダファイルとデータファイルの2本で1セットになります。

ヘッダファイル


テキストファイルでチャンネル情報が記録されます。
ch
Fg
NU
name
comp.
amp
NU
sensitivity
unit
NU
NU
Gain(dB)
qstep(V)
Latitude
Longitude
Elevation
corrP
corrS
を空白で区切って保管されています。
#で始まる行はコメント行。

この中で処理系に依存するのが行数、つまり記録しているチャンネル数。


Winフォーマット



Winフォーマットの構造
|ヘッダ部|データ部| ←ブロック
|ヘッダ部|データ部| ←ブロック
     :
|ヘッダ部|データ部| ←ブロック


ヘッダ部


ブロックサイズヘッド 4 byte

記録年月日ヘッド 6 byte
 |yy|mm|dd|hh|mn|ss|
 yy : 年が下2桁で記録されている

データ部


チャンネルヘッド 4 byte
 |チャンネル名| 2 byte
 | sample info | 2 byte

 チャンネル名
  なぜかHEXで保管。
  例えば チャンネル名 F111 は、hex の f111 で記録されている。
  文字に変換するなら sprintf(“%04x”,chan_name); で処理するとストリング型で見えるチャンネル名にできる。

 sample info : 頭4bit に後続するデータの圧縮サイズが入る。
 0:0.5 byte
 1:1 byte
 2:2 byte
 3:3 byte
 4:4 byte

 sample info : 後ろ 12bit に後続するデータのサンプリングレート(1秒間のデータ数)が入る

チャンネルデータ 可変
 最初の 4 byte は、固定サイズで最初のデータが入っている。
 以降のデータは、sample info のデータ圧縮サイズでデータが入ってる。
 つまり、sample info の圧縮サイズが 2 で、サンプリングレートが100なら
 この可変データのサイズは、
 ( 4byte + 2byte x サンプリングレート – 1 )byte
 となる。

処理系ループ
 ■ブロックループ
  ブロックヘッダ読み込み(get 10byte:ブロックサイズ + 秒ヘッダ)
  fread(blocksize,4,1,ifp); // ブロックサイズ
  fread(sechead,4,1,ifp); // 年月日時刻

  ■チャンネルループ(チャンネル数分)
   0.5byte 用フリップフロップ 初期化—- flipflop = 0
   チャンネルヘッダ読み込み(get 4byte:チャンネル名+データ圧縮サイズ+サンプリングレート)
   fread(ch,4,1,ifp); // チャンネル名
   fread(info,2,1,ifp); // データ圧縮サイズ/サンプリングレート
   comp = ((info[0]&0xf0)>>4)&0x0f);
   late = (info[0]&0x0f) | info[1];

   初期データ読み込み(4byte)—- value
   fread(data_byte,4,1,ifp); // 最初のデータ
   data_topvalue = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
   // データ出力
   // ※データは data_topvalue に作られている
   ■チャンネルデータループ
for(i=0;i<late-1;i++){
  if (comp == 0){
    if (flipflop == 0){
      n = fread(&data_char, 1, 1, ifp);
      data_byte[3] = (data_char & 0xf0) >> 4;
      if ((data_byte[3] & 0x80) == 0x80){
        data_byte[0] = 0xff;
        data_byte[1] = 0xff;
        data_byte[2] = 0xff;
      }
      else{
        data_byte[0] = 0;
        data_byte[1] = 0;
        data_byte[2] = 0;
      }
      data_value = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
      flipflop = 1;
    }
    else{
      data_byte[3] = (data_char & 0xf);
      if ((data_byte[0] & 0x8) == 0x8){
        data_byte[0] = 0xff;
        data_byte[1] = 0xff;
        data_byte[2] = 0xff;
      }
      else{
        data_byte[0] = 0;
        data_byte[1] = 0;
        data_byte[2] = 0;
      }
      data_value = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
      flipflop = 0;
    }
  }
  else if (comp == 1){
    n = fread(&data_byte[3], 1, 1, ifp);
    if ((data_byte[3] & 0x80) == 0x80){
      data_byte[0] = 0xff;
      data_byte[1] = 0xff;
      data_byte[2] = 0xff;
    }
    else{
      data_byte[0] = 0;
      data_byte[1] = 0;
      data_byte[2] = 0;
    }
    data_value = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
  }
  else if (comp == 2){
    n = fread(&data_byte[2], sizeof(unsigned char), 2, ifp);
    if ((data_byte[2] & 0x80) == 0x80){
      data_byte[0] = 0xff;
      data_byte[1] = 0xff;
    }
    else{
      data_byte[0] = 0;
      data_byte[1] = 0;
    }
    data_value = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
  }
  else if (comp == 3){
    n = fread(&data_byte[1], sizeof(unsigned char), 3, ifp);
    if ((data_byte[1] & 0x80) == 0){
      data_byte[0] = 0;
    }
    else{
      data_byte[0] = 0xff;
    }
    data_value = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
  }
  else if (comp == 4){
    n = fread(&data_byte, sizeof(unsigned char), 4, ifp);
    data_value = ((data_byte[0] << 8 | data_byte[1]) << 16) | data_byte[2] << 8 | data_byte[3];
  }
  data_topvalue = data_topvalue + data_value;
  // データ出力
  // ※データは data_topvalue に作られている
}
データを保存するときにできるだけ小さくというのが設計コンセプトらしい。
安全に可変長データを処理するには逐次読みするのが正解。
デバッグしやすいプログラム構造を作るという意味。
バグの入りにくく、処理系ざっくり知識でもプログラムを通読しやすくするという意味でも。

だとしたら、ブロックサイズは不要だし、年月日は、10進数表記の方が 2 byte ほど小さくできる。
データファイルにチャンネル数が存在していない以上チャンネル名は不要となる。
必ずテーブルファイルと照合する必要があるわけだから。

さらに、データの保管方法がきまっていない。
つまり、A社では、1分単位でYYMMDDHHMMという名前でフォルダーをつくってそこに保管とか、
B社では、また別の名前の付け方の規則があったり、さらにテーブルファイルの場所が決まってなかったりする。

といういうことで、Winフォーマットってのは、かなり半端なファイル書式だと思うわけ。
こういうのを統一しないといろんな意味で技術発展の妨げになる。

建築系のデータ書式でDXFとかあるけど、あれも方言が強くてあかんな。
あれの場合は、基本データ部とCAD毎の方言データとか(もちろん共通のものは、共通の名前を使うようにする)を区分けて保管すべきだとか思う。

などと、上から目線で言ってみるwww

スポンサーリンク