如何从 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;
}
我有从某些设备生成的 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;
}