如何从 C++ 读取 .spc 文件?

How can I read a .spc file from C++?

我有从某些设备生成的 PKCS #7 证书 (.spc) 文件。它有一组浮点数,我需要将其读入我的 C++ 程序。

之前,我使用外部程序生成 .csv 文件。但是,我在这里失去了一些精度,因为它只会保存 15 位数字。这是一个问题,我需要精度。

我已经搜索了一段时间,但没有结果。尝试 fstream 或 boost mmap 只会产生一些加密的乱码...

像这样:

F流:

fstream iofile; 
string path = "C:\test.spc";
iofile.open(path.c_str());
if (iofile.is_open()) {
    string s;
    while (getline(iofile, s, '\n'))
        cout << s << endl;
}

提升mmap:

boost::iostreams::mapped_file mmap("C:\test.spc", boost::iostreams::mapped_file::readonly); // create RAM access mmap
auto f = mmap.const_data(); // set data to char array
auto l = f + mmap.size(); // used to detect end of file
string next = ""; // used to read in chars

for (; f && f != l; f++) {
    cout << f[0] << endl;
}

两者都只是输出没有意义的随机字符。

发现是二进制格式。所以我尝试了这个:

streampos size;
char * memblock;

ifstream file("C:\test.spc", ios::in | ios::binary | ios::ate);
if (file.is_open())
{
    size = file.tellg();
    memblock = new char[size];
    file.seekg(0, ios::beg);
    file.read(memblock, size);
    file.close();
    for (unsigned int i = 0; i < size; i++)
        cout << memblock[i];
    cout << endl << "DONE" << endl;
    cout << "the entire file content is in memory";

    delete[] memblock;
}
else cout << "Unable to open file";

比以前多了很多字符,但仍然是随机的。

这是文件的 link: https://drive.google.com/a/uci.edu/file/d/0B3LD-8zOiOdza2FGSVNtbnlSVjQ/view?usp=sharing

已解决。由于它是一个二进制文件,我一直在努力寻找格式。找到它后,我发布了一个 link,其中包含示例文件、代码和 pdf,为任何需要它的人解释格式。这是我用 c++ 编写的一些代码,可以读取它。感谢 Reticulated Spline 的帮助! https://drive.google.com/a/uci.edu/folderview?id=0B3LD-8zOiOdzfjY3YXJEdGlTZ2Z1ekJGNVlJalpYRmRkOHFFaFI4XzZEaWpFbldLSEt3LW8&usp=sharing

#include<stdio.h>
#include <iostream>
#include <iomanip>
#include <map>
using namespace std;

//reads in SPC files according to "new" spc format. Advised to read pdf file, see link below
//This shows how everything is set up, may not be entirely accurate depending on your implementation.
//You can skip memory blocks to make codes shorter, this just shows you what each value represents.
//See PDF for more details on each variable. https://drive.google.com/a/uci.edu/folderview?id=0B3LD-8zOiOdzfjY3YXJEdGlTZ2Z1ekJGNVlJalpYRmRkOHFFaFI4XzZEaWpFbldLSEt3LW8&usp=sharing
//  Also includes example spc file
//Code is as is, I am not liable for any mishaps.
//Open source, do whatever you want with it
//Email for questions: tjohnsen@uci.edu

int main()
{
FILE *ptr_myfile;

// open file
ptr_myfile = fopen("c:\testspc.spc", "rb"); // "rb" to read binary, use "wb" to write binary
if (!ptr_myfile) {
    printf("Unable to open file!");
    return 1;
}

// variables used to store different mem sizes
int i = 0;              // int, 4 bytes
unsigned char b = 'a';  // byte, 1 byte
double d = 0;           // double, 8 bytes
float f = 0;            // float, 4 bytes
short int w = 0;        // word, 2 bytes

// variables we actually need
int power2 = 0; // we use this to multiply to the y value (integer data value representing intensity) later
int numDataPoints = 0; // used to divide first and last x coord, for increments in x values (wavenumbers)
double firstXCoord = 0; // first logged x value (wavenumber)
double lastXCoord = 0; // last logged x value (Wavenumber
int numSubFiles = 1;

// keep track of data
// map< subfile#, map< wavenumber, intensity> > data
map<int, map< double, long double> > data;

// start main folder
fread(&b, sizeof(b), 1, ptr_myfile); // flags represent different things (see pdf)
fread(&b, sizeof(b), 1, ptr_myfile); // spc file version
fread(&b, sizeof(b), 1, ptr_myfile); // experiment type code
fread(&b, sizeof(b), 1, ptr_myfile); // IMPORTANT exponenet for Y values 
    power2 = (int)b; // save our exponent for multiplying
fread(&i, sizeof(i), 1, ptr_myfile); // IMPORTANT number of points in file
    numDataPoints = i; // keep this to divide my min and max x values
fread(&d, sizeof(d), 1, ptr_myfile); // IMPORTANT first x coordinate
    firstXCoord = d; // logs first x value (wavenumber)
fread(&d, sizeof(d), 1, ptr_myfile); // IMPORTANT last x coordinate
    lastXCoord = d; // logs last x value (wavenumber)
fread(&i, sizeof(i), 1, ptr_myfile); // IMPORTANT Number of subfiles 
    numSubFiles = i; // keep track of how man spectra are being kept track of in this binary file
fread(&b, sizeof(b), 1, ptr_myfile); // X units type code
fread(&b, sizeof(b), 1, ptr_myfile); // Y units type code
fread(&b, sizeof(b), 1, ptr_myfile); // Z units type code
fread(&b, sizeof(b), 1, ptr_myfile); // Posting disposition
fread(&i, sizeof(i), 1, ptr_myfile); // compressed date (see pdf for format)
for (unsigned int j = 0; j < 9; j++) // resolution description text
    fread(&b, sizeof(b), 1, ptr_myfile);
for (unsigned int j = 0; j < 9; j++) // source instrument description text
    fread(&b, sizeof(b), 1, ptr_myfile);
fread(&w, sizeof(w), 1, ptr_myfile); // peak point number for interferograms
for (unsigned int j = 0; j < 8; j++) // spare
    fread(&f, sizeof(f), 1, ptr_myfile);
for (unsigned int j = 0; j < 130; j++) // Memo
    fread(&b, sizeof(b), 1, ptr_myfile);
for (unsigned int j = 0; j < 30; j++)  // x, y, and z custom axis strings (combined)
    fread(&b, sizeof(b), 1, ptr_myfile);
fread(&i, sizeof(i), 1, ptr_myfile); // byte offset to log block
fread(&i, sizeof(i), 1, ptr_myfile); // file modification flag
fread(&b, sizeof(b), 1, ptr_myfile); // processing code
fread(&b, sizeof(b), 1, ptr_myfile); // calibration level + 1
fread(&w, sizeof(w), 1, ptr_myfile); // sub method sample injection number
fread(&f, sizeof(f), 1, ptr_myfile); // floatind data multiplier concentration factor
for (unsigned int j = 0; j < 48; j++)  // method file
    fread(&b, sizeof(b), 1, ptr_myfile);
fread(&f, sizeof(f), 1, ptr_myfile); // Z subfile increment for even Z multifiles
fread(&i, sizeof(i), 1, ptr_myfile); // number of w planes
fread(&f, sizeof(f), 1, ptr_myfile); // w plane increment
fread(&b, sizeof(b), 1, ptr_myfile); // w axis units code
for (unsigned int j = 0; j < 187; j++) // reserved
    fread(&b, sizeof(b), 1, ptr_myfile);
// end main header

// do this for all subfiles
for (unsigned int subFile = 0; subFile < numSubFiles; subFile++) {
    // start sub folder for file (Even if only one file here)
    fread(&b, sizeof(b), 1, ptr_myfile); // subfiles flags (See pdf)
    fread(&b, sizeof(b), 1, ptr_myfile); // exponenet for sufiles y values
    if ((int)b != 0) // my files at least had this area blank sinc had only one sub file
        power2 = (int)b; // multiple sub files may have his changed, make sure to check other values for similar things
    fread(&w, sizeof(w), 1, ptr_myfile); // subfile index number
    fread(&f, sizeof(f), 1, ptr_myfile); // subfiels starting z value
    fread(&f, sizeof(f), 1, ptr_myfile); // subfiles ending z value
    fread(&f, sizeof(f), 1, ptr_myfile); // subfiles noise value to use peak picking
    fread(&i, sizeof(i), 1, ptr_myfile); // number of points if XYXY multifile
    fread(&i, sizeof(i), 1, ptr_myfile); // number of co-added scans
    fread(&f, sizeof(f), 1, ptr_myfile); // w axis value
    for (unsigned int j = 0; j < 4; j++) // reserved
        fread(&b, sizeof(b), 1, ptr_myfile);
    // end sub header for file

    // get increment if just lists y values, and not in XY format
    double increment = (lastXCoord - firstXCoord) / (numDataPoints-1);
    double waveNumber = firstXCoord;

    // start data entry for only x values
    for (unsigned int j = 0; j < numDataPoints; j++) {
        fread(&i, sizeof(i), 1, ptr_myfile); // read in data value
        long double intensity = i * pow(2, power2) / (pow(2, 32)); // use pow(2, 16) in bottom fraction instead if data stored as 16-bit rather than 32-bit
        data[subFile][waveNumber] = intensity; // store intensity
        if ( j <= 5)
        cout << waveNumber << " = " << intensity << endl;
        waveNumber += increment; // add increment to x value
    }
    // end data for x values
}

fclose(ptr_myfile);
cout << "SPC FILE READ" << endl;
int k;
cin >> k;
return 0;
}