2016-08-30 4 views
0

Ich habe eine binäre Datei, die das folgende Format hat:Doppel Werte und int Werte von Binärdatei Lesen

# vtk DataFile Version 4.0 
vtk output 
BINARY 
DATASET POLYDATA 
POINTS 10000 double 
?�T�����?����h�?�T�����?���� <-- 10000 double values (in binary format) follow separated by space and new line after every 9 values. 

Ich mag diese Datei Byte für Byte lesen, so dass ich diese doppelten Werte in meinem Array speichern kann . Ich habe den folgenden Code, der diese Datei in ein char * -Puffer-Array lädt. Jetzt möchte ich wissen, wie man weiter vorgeht?

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

int main() { 

    ifstream is ("Data_binary.vtk", ifstream::binary); 
    if (is) { 
    // get length of file: 
    is.seekg (0, is.end); 
    unsigned long length = is.tellg(); 
    is.seekg (0, is.beg); 

    char * buffer = new char [length+1]; 
    buffer[length] = '\0'; 

    cout << "Reading " << length << " characters... "; 
    // read data as a block: 
    is.seekg(0, is.beg); 
    is.read (buffer,length); 

    if (is) 
     cout << "all characters read successfully." << endl; 
    else 
     cout << "error: only " << is.gcount() << " could be read"; 
    is.close(); 
    } 

    return 0; 
} 

Im ASCII-Format wäre eine Beispieldatei wie folgt aussehen:

# vtk DataFile Version 4.0 
vtk output 
ASCII 
DATASET POLYDATA 
POINTS 18 double 
.1 .2 .3 1.4 11.55 1 0 8e-03 5.6 
1.02 2.2 3.3 .1 .5 0.001 4e-07 4.2 1.55 

Für binäre Datei, die doppelten Werte in binärer vorhanden sind. Ich möchte doppelte Werte aus dem Binärformat erhalten.

+0

Insbesondere [@ Sehes Antwort] (http://stackoverflow.com/a/7828841/1413395) sieht aus wie der Weg zu gehen. Es muss jedoch 'boost :: spirit' verwendet werden. –

+0

@ πάντα ῥεῖ Ich habe Daten in Binärdatei. Ich möchte lernen, Binärdaten byteweise zu lesen, um Zeichen zu erhalten, oder Bytefolgen zu lesen, um doppelte/ganzzahlige Werte zu erhalten. – Jaipreet

+0

Das ist keine Binärdatei. Was Sie beschreiben, ist genau das '.vdk' Dateiformat (siehe [hier] (http://dunne.uni-hd.de/VisuSimple/documents/vtkfileformat.html) bitte) –

Antwort

0

Anstatt in einen char * Puffer zu lesen, lesen Sie in einen double * Puffer. Casting zu/von char * ist nur für diesen Zweck erlaubt.

vector<double> buffer; 
buffer.resize(n); 
is.read(reinterpret_cast<char *>(&buffer[0]), n * sizeof(buffer[0])); 

Sie müssen zuerst die nicht binären Daten lesen, so dass sich der Dateizeiger am Anfang der Binärdaten befindet. Dies ist definiert als unmittelbar nach dem Newline-Zeichen des letzten Felds in der Kopfzeile.

Die Spezifikation scheint kein Little-Endian- oder Big-Endian-Format zu erfordern, sondern erwartet, dass Sie basierend auf der Quelle der Datei wissen. Wenn Sie Glück haben, stimmt das Format mit dem Computer überein, den Sie zum Lesen der Datei verwenden, und es ist keine Konvertierung erforderlich. Andernfalls müssen Sie ein Byte-Swap tun:

void ByteSwap(double * p) 
{ 
    char * pc = reinterpret_cast<char *>(p); 
    std::swap(pc[0], pc[7]); 
    std::swap(pc[1], pc[6]); 
    std::swap(pc[2], pc[5]); 
    std::swap(pc[3], pc[4]); 
} 
1
Use this function. 


/* 
* read a double from a stream in ieee754 format regardless of host 
* encoding. 
* fp - the stream 
* bigendian - set to if big bytes first, clear for little bytes 
*    first 
* 
*/ 
double freadieee754(FILE *fp, int bigendian) 
{ 
    unsigned char buff[8]; 
    int i; 
    double fnorm = 0.0; 
    unsigned char temp; 
    int sign; 
    int exponent; 
    double bitval; 
    int maski, mask; 
    int expbits = 11; 
    int significandbits = 52; 
    int shift; 
    double answer; 

    /* read the data */ 
    for (i = 0; i < 8; i++) 
     buff[i] = fgetc(fp); 
    /* just reverse if not big-endian*/ 
    if (!bigendian) 
    { 
     for (i = 0; i < 4; i++) 
     { 
      temp = buff[i]; 
      buff[i] = buff[8 - i - 1]; 
      buff[8 - i - 1] = temp; 
     } 
    } 
    sign = buff[0] & 0x80 ? -1 : 1; 
    /* exponet in raw format*/ 
    exponent = ((buff[0] & 0x7F) << 4) | ((buff[1] & 0xF0) >> 4); 

    /* read inthe mantissa. Top bit is 0.5, the successive bits half*/ 
    bitval = 0.5; 
    maski = 1; 
    mask = 0x08; 
    for (i = 0; i < significandbits; i++) 
    { 
     if (buff[maski] & mask) 
      fnorm += bitval; 

     bitval /= 2.0; 
     mask >>= 1; 
     if (mask == 0) 
     { 
      mask = 0x80; 
      maski++; 
     } 
    } 
    /* handle zero specially */ 
    if (exponent == 0 && fnorm == 0) 
     return 0.0; 

    shift = exponent - ((1 << (expbits - 1)) - 1); /* exponent = shift + bias */ 
    /* nans have exp 1024 and non-zero mantissa */ 
    if (shift == 1024 && fnorm != 0) 
     return sqrt(-1.0); 
    /*infinity*/ 
    if (shift == 1024 && fnorm == 0) 
    { 

#ifdef INFINITY 
     return sign == 1 ? INFINITY : -INFINITY; 
#endif 
     return (sign * 1.0)/0.0; 
    } 
    if (shift > -1023) 
    { 
     answer = ldexp(fnorm + 1.0, shift); 
     return answer * sign; 
    } 
    else 
    { 
     /* denormalised numbers */ 
     if (fnorm == 0.0) 
      return 0.0; 
     shift = -1022; 
     while (fnorm < 1.0) 
     { 
      fnorm *= 2; 
      shift--; 
     } 
     answer = ldexp(fnorm, shift); 
     return answer * sign; 
    } 
} 

es ist viel, aber es ist nur ein Ausschnitt zum Ausschneiden und Einfügen, und Sie müssen nie wieder über binäre Gleitkommaformate kümmern. Es liest einfach ein IEEE-754-Double, unabhängig vom Host-Gleitkommaformat. Es gibt einen Zwilling, der schreibt