바이너리 포맷 읽기

게시판 IDL Q&A 바이너리 포맷 읽기

3 답변 글타래를 보이고 있습니다
  • 글쓴이
    • #1392 Reply
      chobo
      회원

      안녕하세요.
      바이너리 포맷 읽기 관련하여 문의드립니다.
      기상레이더의 한 포맷인 dorade 자료를 읽을려고 합니다.
      아래처럼 코드를 작성해봤는데, id만 “RYIB”으로 제대로 읽힌것 같고, 나머지는 모두 조금 이상해 보입니다. nbytes(크기)는 44 가 맞으나, 조금 이상해 보이구요. 아마도 제가 자료형의 이해를 잘 못 하고 있는 것 같아서 발생한 초보적인 문제인 것 같은데, 무엇이 잘 못 된 것일까요?
      감사합니다.

      pro dorade_io
      FP = ‘F:/DORADE/080529/’
      file=’swp.1080529010200.SPOLRVP8.0.1.0_’
      data = READ_BINARY( fp+file)
      rm=!null
      for i = 0L, n_elements(data)-4L do begin
      if string(data[i:i+3L]) eq ‘RYIB’ then rm = [[rm], [i, i+3L]]
      endfor

      ; ******** Data Format *************************************
      ;Offset-bytes Data type Bytewidth Count Item
      ;———– ——— ——— ——— ———-
      ;0 char 1 4 id
      ;4 integer 4 1 nbytes
      ;8 integer 4 1 sweep_num
      ;12 integer 4 1 julian_day
      ;16 integer 2 1 hour
      ;18 integer 2 1 minute
      ;20 integer 2 1 second
      ;22 integer 2 1 millisecond
      ;24 float 4 1 azimuth angle in degree
      ;28 float 4 1 elevation angle in degree
      ;32 float 4 1 peak_power
      ;36 float 4 1 true_scan_rate
      ;40 integer 4 1 ray_status
      ;************************************************************

      for i = 0, n_elements(rm[0, *])-1 do begin

      offset = rm[i]

      id = string(data[offset+0L:offset+3]) & print, ‘id:’, id
      nbyte= fix(data[offset+4L:offset+7L]) & print, ‘nbyte:’, nbyte
      sweep_num = fix(data[offset+8L:offset+11L]) & print, ‘sweep_num:’, sweep_num
      juluday = fix(data[offset+12L:offset+15L]) & print, ‘juluday:’, juluday
      hour = fix(data[offset+16L:offset+17L]) & print, ‘hour:’, hour
      minute = fix(data[offset+18L:offset+19L]) & print, ‘minute:’, minute
      second = fix(data[offset+20L:offset+21L]) & print, ‘second:’, second
      milisecond = fix(data[offset+22L:offset+23L]) & print, ‘milisecond:’, milisecond
      az = float(data[offset+24L:offset+27L]) & print, ‘az:’, az
      el = float(data[offset+28L:offset+31L]) & print, ‘el:’, el
      peak_power= float(data[offset+32L:offset+35L]) & print, ‘peak_power:’, peak_power
      scan_rate = float(data[offset+36L:offset+39L]) & print, ‘scan_rate:’, scan_rate
      ray_status= fix(data[offset+40L:offset+43L]) & print, ‘ray_status:’, ray_status
      stop
      endfor

      ====== IDL printed ======
      IDL> dorade_io
      % Compiled module: DORADE_IO.
      id:RYIB
      nbyte: 44 0 0 0
      sweep_num: 1 0 0 0
      juluday: 150 0 0 0
      hour: 1 0
      minute: 2 0
      second: 0 0
      milisecond: 0 0
      az: 34.0000 148.000 160.000 67.0000
      el: 26.0000 81.0000 122.000 63.0000
      peak_power: 176.000 51.0000 161.000 77.0000
      scan_rate: 0.000000 0.000000 0.000000 199.000
      ray_status: 0 0 0 0
      % Stop encountered: DORADE_IO 53 F:\DORADE\dorade_io.pro
      IDL>

    • #1393 Reply
      chobo
      회원

      위 코드 에서 offset = rm[i]를 offset = rm[0, i] 로 수정합니다.

    • #1395 Reply
      JongHyeon
      회원

      코드 내에서 잘못된 점은 fix나 float등이 배열들의 개별값을 변환하는 함수라는 점입니다.
      nbyte= fix(data[offset+4L:offset+7L]) & print, ‘nbyte:’, nbyte
      에서 출력이
      nbyte: 44 0 0 0
      라고 되는데요.
      보시면 data라는 byte array의 data[offset+4L:offset+7L]의 결과가 배열이 됩니다.

      따라서 nbyte를 포함한 fix,float로 변환하는 변수들을 help로 확인하면
      <Expression> INT = Array[4]
      등으로 출력이 됩니다. (fix를 이용했으면 int, float를 이용하면 float)

      단 string은 byte를 char로 판단하기 때문에 byte array를 넣으면 정상적으로 출력됩니다. 따라서 id는 제대로 출력이 된 것이지요.

      참고로 byte array로 출력된 데이터를 다른형으로 맞춰서 변환하는 것이 힘들기 때문에 처음 파일을 읽을 때 데이터형에 따라서

      char형은 bytarr(4) [예)id = bytarr(4)]
      integer4형은 IDL의 long [예) nbyte=0L]
      integer2형은 IDL의 int
      float4형은 IDL의 float

      와 같이 변수를 우선 생성하고,

      openr,1,fp+file

      로 파일을 열어서

      readu,id,nbyte,sweep_num …

      식으로 파일을 읽으면 될 것 같습니다.

    • #1405 Reply
      chobo
      회원

      매번 감사합니다.
      덕분에 실마리를 찾은 것 같습니다. ^^

3 답변 글타래를 보이고 있습니다
'바이너리 포맷 읽기'에 답변달기
글쓴이 정보: