LoginSignup
6
7

More than 5 years have passed since last update.

Swiftでバイナリデータをstructで扱う

Last updated at Posted at 2018-10-31

※Swift4です

Swiftでバイナリデータを扱う

SwiftではバイナリデータをData型で扱うことができます。

let data = Data(...)

data[0] // -> UInt8
data[1] // -> UInt8
...

Int8は1バイトのデータのことであるため、data配列をいい感じに操作すればバイナリデータを扱うことができそうです。

structで扱いたい

たとえば、バイナリデータが |type 2byte|data 4byte|type 2byte|data 4byte|...というデータの並びになっているとき、

struct SingleData {
  let type: UInt16
  let data: UInt32
}

上↑のようなstructを用意して、読み込んだ後に配列に変換してから操作すると楽そうです。

var isEnd = false
var counter = 0;
var datas: [SingleData] = []
while isEnd {
  let type: UInt16 = 
    UInt16(data[counter * 0]) << 8 + 
    UInt16(data[counter * 1])
  let data: UInt32 = 
    UInt32(data[counter * 2]) << 8 * 3 +
    UInt32(data[counter * 3]) << 8 * 2 +
    UInt32(data[counter * 4]) << 8 * 1 +
    UInt32(data[counter * 5]) << 8 * 0

  datas.append(SingleData(type: type, data: data))
}

... // 以下、datasを好きに使う

...けっこう大変ですね。

C言語だと、「共用体」と呼ばれる複数の型として操作できる型を使うことでバイナリデータをわりと簡単にstructとして扱うことができましたが、Swiftではどうなのでしょうか。

Swiftでバイナリデータをstructとして扱う

答えは、「withUnsafeBytesを使う。」です。これによってそれなりに簡単にstructに変換することができるようになります。

// 値を return すると withUnsafeBytes の戻り値となる
let results = data.withUnsafeBytes({(ptr: UnsafePointer<SingleData>) -> [SingleData] in
  let count = data.count / MemoryLayout<SingleData>.size // データの個数を計算
  var tmp = ptr // ptr を var にしたい
  var results: [SingleData] = []
  for i in 0..<count {
    // ptr.pointee で中身にアクセスできる。 *ptr みたいなもの?
    results.append(ptr.pointee)
    // ポインタを隣に移動する。 ptr++ みたいなもの?
    ptr.successor()
  }
})

... // results を好きに操作する

注意

structのプロパティにはlittle endianでアクセスします。
したがって、読み込むデータ(2byte以上)によってはbig endianでアクセスする必要があります。

type data
0x0001 0x12345678
0x0002 0x12345678
0x0003 0x12345678

上↑のようなデータだったとき、results[0].type == 256(0x0100)となってしまいます。
もし、データがbig endianで格納されているのであれば、bigEndianプロパティを使ってアクセスしましょう。

こうです。

print(results[0].type.bigEndian)

JPEGを読み込むプログラムを書こうと思ったのですが、big endianでアクセスするのがめっちゃ面倒だったので、諦めました。

以上です。よろしくお願いいたします。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7