2014-07-18 2 views
0

Я имею двоичную строку с ASCII, как этоReplicate распаковщики Perl в C++

^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^O^@^@^@^@^@^BU -^@^@^@^A^@^@^O^@^@^@^@^@^BÜ -^@^@^@^A^@^@^@^@^@^@^@^@^EÜ?^@^@^@^A^@^@^ @^@^@^@^@^@^Eu?^@^@^@^A^@^@. а^@^@^@^@^@^HAD^@^@^@^A^@^@ .^^ @^@^@^@^@^Häð^@^@^@^A^@^@> < 80>^@^@^@^@^@^KÖ < 80>^@^@^@^A^@^@> < 80>^

Perl код:

#!/usr/bin/env perl 
use warnings; 
use strict; 
use Data::Dumper; 

open(INDEX, $ARGV[0]); 
binmode(INDEX); 

my $buff; 

my $ret = read(INDEX, $buff, 4); 
my $fragment = unpack 'N', $buff; 

$ret = read(INDEX, $buff, 4); 
my $timestamp = unpack 'N', $buff; 

$ret = read(INDEX, $buff, 8); 
my $offset = unpack 'N', $buff; 

print "timestamp = $timestamp fragment # $fragment offset = $offset\n"; 

Выход:

timestamp = 0 fragment # 1 offset = 0 
timestamp = 0 fragment # 1 offset = 0 
timestamp = 0 fragment # 1 offset = 0 
timestamp = 0 fragment # 1 offset = 0 
timestamp = 4000 fragment # 1 offset = 187437 
timestamp = 4000 fragment # 1 offset = 187437 
timestamp = 8000 fragment # 1 offset = 384063 
timestamp = 8000 fragment # 1 offset = 384063 
timestamp = 12000 fragment # 1 offset = 582896 
timestamp = 12000 fragment # 1 offset = 582896 

Я хочу повторить вышеуказанную работу, проделанную распаковываем в C++ Как это сделать?

То, что я пытался:

#include <iostream> 
#include <stdlib.h> 
using namespace std; 

int main() 
{ 
    int k; 
    char buf1[5]; 
    char buf2[5]; 
    char buf3[9]; 
    int i; 
    char *str; 
    //Assume str contains the entire binary data 

    for(int i=0;str[i];) 
    { 
     while(k<32) 
    { 
      buf1[k]=str[i]; 
      ++k;++i; 
    } 
    k=0; 
    while(k<32) 
    { 
      buf2[k]=str[i]; 
      ++k; 
    } 
    k=0; 
    while(k<64) 
    { 
      buf3[k]=str[i]; 
      ++k;++i; 
    } 
    k=0; 
    uint32_t a1,b1,a2,b2; 
    uint64_t a3,b3; 
    a1=atoi(buf1); 
    b1=ntohl(a1); 

    a2=atoi(buf2); 
    b2=ntohl(a2); 

    a3=atoi(buf1); 
    b3=ntohl(a3); 

    print "timestamp ="<< b2 << "fragment #"<<b1<<" offset ="<<b3<<"\n"; 
    } 
return 0; 

}

+0

Я хочу, чтобы код C++ выполнял то, что делает скрипт perl! – Ram

+0

1) выясните, что представляет собой каждое из значений байта, 2) прочитайте их, 3) используя идеи из 1, снова соберите их в нужные вам значения времени. Вы можете начать с 'std :: ifstream' для чтения, и я бы предположил, что значения будут в некотором довольно стандартном формате: вы можете, вероятно, прочитать их непосредственно в' uintint32_t' и, возможно, потребуется запустить ['ntohl' ] (http://linux.die.net/man/3/ntohl) над ними. Отправьте свой код ***, когда вы действительно что-то пробовали ***, и люди помогут вам. –

+0

Извините, что я делал. Можете ли вы меня исправить? – Ram

ответ

-1

Чтение 4 байта, а затем использовать

uint32_t n; 
n = buf[0] << 24 
    | buf[1] << 16 
    | buf[2] << 8 
    | buf[3] << 0; 

Например,

uint32_t n; 
unsigned char buf[4]; 
size_t bytes_read = fread (buf, 1, 4, stream); 
if (bytes_read < 4) { 
    if (ferror(stream)) { 
     // Error 
     // ... 
    } 
    else if (feof(stream)) { 
     // Premature EOF 
     // ... 
    } 
} 
else { 
    n = buf[0] << 24 
    | buf[1] << 16 
    | buf[2] << 8 
    | buf[3] << 0; 
} 
2

Здесь вы идете:

#include <stdint.h> 
#include <iostream> 
#include <fstream> 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
    if (argc < 2) 
    { 
     cerr << "Input filename required" << endl; 
     return 1; 
    } 

    ifstream f(argv[1], ios::binary); 
    if (!f.good()) 
    { 
     cerr << "Cannot open input file '" << argv[1] << "'" << endl; 
     return 1; 
    } 

    while (!f.eof()) 
    { 
     uint8_t buf[8]; 

     f.read(reinterpret_cast< char * >(buf), 4); 
     uint32_t fragment = ((buf[0] * 256U + buf[1]) * 256U + buf[2]) * 256U + buf[3]; 

     f.read(reinterpret_cast< char * >(buf), 4); 
     uint32_t timestamp = ((buf[0] * 256U + buf[1]) * 256U + buf[2]) * 256U + buf[3]; 

     f.read(reinterpret_cast< char * >(buf), 8); 
     uint64_t offset = ((((((buf[0] * 256LL + buf[1]) * 256LL + buf[2]) * 256LL + buf[3]) 
      * 256LL + buf[4]) * 256LL + buf[5]) * 256LL + buf[6]) * 256LL + buf[7]; 

     if (f.good()) 
     { 
      cout << "timestamp = " << timestamp; 
      cout << " fragment = " << fragment; 
      cout << " offset = " << offset << endl; 
     } 
    } 

    return 0; 
} 
+0

Большое спасибо Khouri Giordano !! Он работает как charm.One небольшое сомнение. Что, если вход хранится в std :: string вместо файла? В этом случае что использовать вместо f.read (reinterpret_cast < char * > (buf), 4); f.read (reinterpret_cast < char * > (buf), 4); f.read (reinterpret_cast < char * > (buf), 8); я довольно новичок в C++, так что простите меня, если я задаю основы – Ram

+0

Весь смысл 'f.read (reinterpret_cast < char * > (buf), 4)' - получить байты в строку. Вы просто пропустите шаг и используйте код, который я опубликовал ранее. – ikegami

+0

ikegami..Two вопросы .. во-первых, вы прочитали из файла в массив символов, а затем сделали левый и правый сдвиг на нем .. это нормально? я выполнил ваш код, не получил желаемый результат, поэтому прошу ... во-вторых, вы читаете от 1 до 4 байт изначально .. после этого нужно от 4 до 8, а затем от 8 до 16. Это чтение происходит из строки, а не из файла. .как это сделать? У меня нет опыта кодирования, поэтому полноценный рабочий код будет действительно полезен.спасибо заранее и извините, если я ошибаюсь – Ram