2015-03-09 1 views
3

Я пытаюсь читать буферизованный поток подписанных 16-битных целых чисел (wav-формат), но метод bufio.Read принимает только массив байтов. Мой вопрос: 2-партер:Golang: Чтение буферизованного ввода как подписанного 16-битного ints

  1. Могу ли я предварительно форматировать поток байтов в буферизованный массив int16?
  2. Если я не могу, то лучший способ постображения массива байтов в массив int16? Моя первоначальная мысль состоит в том, чтобы использовать массивы tmp и продолжать толкать/обрабатывать их, но мне было любопытно, есть ли более идиоматический способ сделать это?

    package main 
    
    import (
        "bufio" 
        "io" 
        "log" 
        "os/exec" 
    ) 
    
    func main() { 
    
        app := "someapp" 
    
        cmd := exec.Command(app) 
        stdout, err := cmd.StdoutPipe() 
        r := bufio.NewReader(stdout) 
        if err != nil { 
         log.Fatal(err) 
        } 
        if err := cmd.Start(); err != nil { 
         log.Fatal(err) 
        } 
    
        //"someapp" outputs signed 16bit integers (little endian)) 
        buf := make([]byte, 0, 4*1024) 
    
        for { 
         n, err := r.Read(buf[:cap(buf)]) //r.Read only accepts type []byte 
         buf = buf[:n] 
         if n == 0 { 
          if err == nil { 
           continue 
          } 
          if err == io.EOF { 
           break 
          } 
          log.Fatal(err) 
         } 
    
         log.Printf("%x\n", buf) 
         //process buf here 
    
         if err != nil && err != io.EOF { 
          log.Fatal(err) 
         } 
        } 
    } 
    
+0

Несвязанного к проблеме под руку, но ваш код не соответствует семантике [ 'io.Reader'] (https://golang.org/pkg/io/# Читатель). (Оказывается, реализация ['bufio.Buffer''s] (https://golang.org/pkg/bufio/#Reader.Read) документирована как более строгая, но в целом лучше всего предположить любое' io. Reader'). –

ответ

1

Вы можете использовать encoding/binary.Read для заполнения []int16 непосредственно от своего читателя, хотя технически ответ на ваш первый вопрос до сих пор нет (проверьте источник binary.Read, считывает данные к []byte первым) ,

3

При работе с IO, вы всегда работать с []byte с, нет никакого способа, чтобы заменить, что с []int16 или предварительно формате, который, как int16 с, это всегда поток байтов.

Вы можете посмотреть пакет encoding/binary, чтобы декодировать этот поток.

// to get the first uint16 as i 
i := binary.LittleEndian.Uint16(buf[:2]) 

После этого вы можете выполнить итерацию через буфер.

Вы также можете использовать binary.Read для чтения непосредственно с io.Reader.

var i uint16 
for { 
    err := binary.Read(r, binary.LittleEndian, &i) 
    if err != nil { 
     log.Println(err) 
     break 
    } 
    fmt.Println(i) 
} 

Возможно, стоит отметить простоту того, что необходимо сделать. Каждый uint16 создаются с помощью:

func (littleEndian) Uint16(b []byte) uint16 { 
    return uint16(b[0]) | uint16(b[1])<<8 
} 
+0

Похоже, я должен перебирать массив [как это] (http://play.golang.org/p/YPw2j8cc3d)? Существует не метод int16 для двоичного. Читайте, поэтому я теряю знак, но это может быть преобразовано, когда мне это нужно. – cannadayr

+0

@smileybone: Да, это работает, просто проверьте, что у вас всегда есть 2 байта для работы в конце среза. Нет метода Int16, потому что вы просто конвертируете его из uint16 (библиотека делает это внутренне, когда это необходимо, посмотрите на источник функции binary.Read) – JimB