我在上一篇文章中描述了wis二进制文件的结构(wis是石油测井软件Forward中的一种二进制文件格式,很多软件需要转换为文本才可使用),然后用纯C编写了转换程序,利用Python编写了界面调用这个程序,在这里我利用C++重新编写了这个程序,当然和C编写的区别不大,主要的区别在内存分配、读取二进制文件和写入文本文件的函数上,也是为了说明C与C++文件操作上的一些区别,有兴趣的朋友可以和上一遍文章对比一下,技术有限,仅供参考!
以下是C++源代码:
<textarea cols="50" rows="15" name="code" class="cpp">/* * Copyright (c) 2011, Sun Yunqiang * All rights reserved. * Software: wis2txt_win.cpp * Version: 1.0 * Author: Sun Yunqiang * English Name: Alex Sun * Release Date: 18/03/2011 */ /** ***************************************************************** */ /** This Program is for converting wis format file to txt format file */ /** Command: wis2txt_win.exe args1 args2 */ /** Description: */ /** wis2txt_win.exe: the executable file as command */ /** args1: the first argument that is the wis file name */ /** args2: the second argument that is the txt file name */ /** ***************************************************************** */ #include <windows.h> #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <cstdlib> #include <cctype> #include <ctime> #include <cmath> #define ROW 65536 #define COL 512 /* **************************************** */ /* Below blocks are the structs of wis file */ /* **************************************** */ typedef struct tagWIS_HEAD { WORD MachineType; // 0-PC 1-SUN 2-IBM 3-HP WORD MaxObjectNumber; WORD ObjectNumber; WORD BlockLen; DWORD EntryOffset; DWORD DataOffset; DWORD FileSize; time_t TimeCreate; char Reserved[32]; }WIS_HEAD; typedef struct tagWIS_OBJECT_ENTRY { char Name[16]; long Status; short Attribute; // 1-通道对象 2-表对象 3-流对象 short SubAttribute; // 1-曲线对象 2-波形对象 3-地层测试对象 4-时深时对象 DWORD Position; // 对象数据体从文件开始处的偏移量 DWORD BlockNum; time_t TimeCreate; time_t TimeWrite; char Reserved[32]; }WIS_OBJECT_ENTRY; typedef struct tagWIS_CHANNEL_DIMENSION { char Name[8]; char Unit[8]; char AliasName[16]; float StartVal; float Delta; DWORD Samples; DWORD MaxSamples; DWORD Size; WORD RepCode; WORD Reserved; }WIS_CHANNEL_DIMENSION; typedef struct tagWIS_CHANNEL { char Unit[8]; char AliasName[16]; char AliasUnit[16]; WORD RepCode; WORD CodeLen; float MinVal; float MaxVal; WORD Reserved; WORD NumOfDimension; WIS_CHANNEL_DIMENSION DimInfo[4]; }WIS_CHANNEL; typedef struct tagWIS_STREAM { DWORD Length; DWORD Offset; }WIS_STREAM; typedef struct tagWIS_TABLE_FIELD { char Name[32]; WORD RepCode; WORD Length; DWORD Reserved; } WIS_TABLE_FIELD; typedef struct tagWIS_TABLE { DWORD RecordCount; DWORD FieldCount; WIS_TABLE_FIELD *pField; }WIS_TABLE; typedef struct tagWIS_TABLE_DEFAULT_FILED { char Name[16]; char Alias[16]; char Unit[8]; char Type[8]; WORD Length; WORD Count; char DefVal[64][12]; } WIS_TABLE_DEFAULT_FIELD; typedef struct tagWIS_DEFAULT_TABLE { char Name[16]; char Alias[16]; char Attrb[8]; DWORD FieldCount; WIS_TABLE_DEFAULT_FIELD *pField; } WIS_DEFAULT_TABLE; /* 曲线的信息结构体*/ typedef struct tagCURVE_HEAD { char Name[16]; // 曲线的名字 char Unit[8]; // 曲线的单位 float startMD; // 曲线的起始深度 float stopMD; // 曲线的结束深度 int pointNum; // 数据样点数 int position; // 数据位置 struct tagCURVE_HEAD *next; } CURVE_HEAD; /* 曲线的数据结构体 */ typedef struct tagCURVE_DATA { char Name[16]; // 曲线的名字 char Unit[8]; // 曲线的单位 float Depth[ROW]; // 曲线的深度值 float Value[ROW]; // 曲线的值 struct tagCURVE_DATA *next; } CURVE_DATA; /* ************************************************************* */ /* Below block is the Main program of processing wis format file */ /* ************************************************************* */ int main(int argc, char *argv[]) { std::ifstream wisfile; // 输入文件 std::ofstream txtfile; // 输出文件 char *infilename = argv[1]; char *outfilename = argv[2]; // char *infilename = "demoa.wis"; // char *outfilename = "demoa.txt"; if(argc != 3 ) { std::cerr<<"ERROR: Command parameters is not defined correctly!"<<std::endl; exit(1); } wisfile.open(infilename, std::ios::binary); if(!wisfile.is_open()) { std::cerr<<"ERROR: Read file terminated!"<<std::endl; exit(1); } txtfile.open(outfilename); if(!txtfile.is_open()) { std::cerr << "ERROR: Write file terminated!" << std::endl; exit(1); } /* Process wis file, Read it and transfer it to text */ /** wis文件标识符从文件偏移0开始,为10个字节的字符 */ char wisid[10]; wisfile.read(wisid, 10); std::cout<<"文件标识符: WIS" << wisid[4] << wisid[5] << wisid[6] << std::endl; txtfile << "WIS" << wisid[4] << wisid[5] << wisid[6] << " to ASCII TEXT by SUNYQ/n"; /** 头文件紧接文件标识 */ WIS_HEAD *wishead = new WIS_HEAD; wisfile.seekg(10, std::ios::beg); wisfile.read(reinterpret_cast<char *>(wishead), sizeof(WIS_HEAD)); // 对象入口记录从文件开始的偏移量: wishead->EntryOffset // 对象数据记录从文件开始的偏移量: wishead->DataOffset // 当前记录的对象总数: wishead->ObjectNumber /** 对象入口,位置由头结构中EntryOffset参数指定 最多512条曲线 */ wisfile.seekg(wishead->EntryOffset, std::ios::beg); delete wishead; /** curvePosition数组 保存曲线数据开始的位置 WIS_OBJECT_ENTRY->Position的值 */ /** curveName数组 保存每条曲线的名称 */ /** curveNum变量 文件中保存曲线的数目 */ int curvePosition[512]; int curveName[512][16]; int curveNum = 0; // curveNum is the identifer of the curves number while(1) { WIS_OBJECT_ENTRY *objectEntry; objectEntry = new WIS_OBJECT_ENTRY; wisfile.read(reinterpret_cast<char *>(objectEntry), sizeof(WIS_OBJECT_ENTRY)); if(objectEntry->Attribute == 0) { break; } else if(objectEntry->Attribute == 1) { // 通道类型: objectEntry->Attribute // 曲线名字: objectEntry->Name // 对象数据体绝对偏移量: objectEntry->Position curvePosition[curveNum] = objectEntry->Position; int i=0; for(i=0; i<16; i++) { curveName[curveNum][i] = objectEntry->Name[i]; } curveNum++; } else { continue; } delete objectEntry; } std::cout << infilename << " 文件的曲线数目: " << curveNum << std::endl; /* ****************************************************************** */ /* Below block read every curve head information and put it in a link */ /* ****************************************************************** */ /** 创建链表 data_node 开始读取数据 */ /** num变量 每条曲线的行数 */ CURVE_HEAD *first_head = NULL; float delta = 0.0; CURVE_HEAD *data_head = NULL; int num = 0; for(num = 0; num < curveNum ; num++) // num相当于第几条曲线 { data_head = new CURVE_HEAD; data_head->position = curvePosition[num]; wisfile.seekg(curvePosition[num], std::ios::beg); WIS_CHANNEL *channel; channel = new WIS_CHANNEL; wisfile.read(reinterpret_cast<char *>(channel), sizeof(WIS_CHANNEL)); data_head->pointNum = channel->DimInfo[0].MaxSamples; // 深度采样点的个数 data_head->startMD = channel->DimInfo[0].StartVal; // 起始深度 delta = channel->DimInfo[0].Delta; // 间隔点值 data_head->stopMD = channel->DimInfo[0].StartVal + delta * channel->DimInfo[0].MaxSamples; // 结束深度 int i = 0; for(i=0; i<16; i++) { data_head->Name[i] = curveName[num][i]; } for(i=0; i<8; i++) { data_head->Unit[i] = channel->Unit[i]; } std::cout << "No." << num+1 << "/t"; // 曲线编号 std::cout << data_head->Name << "/t"; // 曲线名 std::cout << data_head->Unit << "/t"; // 曲线单位 std::cout << data_head->pointNum << "/t"; // 采样点数 std::cout << delta << "/t"; // 采样点间隔 std::cout << data_head->startMD << "/t"; // 起始深度 std::cout << data_head->stopMD << std::endl; // 结束深度 data_head->next = first_head; first_head = data_head; } std::cout << "Waiting..." << std::endl; /* *********************************************************************** */ /* Below block is for deciding the min and max Depth, and the max line num */ /* *********************************************************************** */ // 从这里开始判断所有曲线中最小深度和最大深度值 float minDepth = 0.0; float maxDepth = 0.0; minDepth = first_head->startMD; maxDepth = first_head->stopMD; for(data_head = first_head; data_head!= NULL; data_head=data_head->next) { if(minDepth>data_head->startMD) { minDepth = data_head->startMD; // 确定最小深度值 } if(maxDepth < data_head->stopMD) { maxDepth = data_head->stopMD; // 确定最大深度值 } } // 利用最小最大深度值和间隔点值,确定输出的采样点数 float depth[ROW]; int lineNum = 0; lineNum = (maxDepth - minDepth) / delta; // 采样点个数:lineNum int row=0; for(row=0; row<lineNum; row++) { depth[row] = minDepth + delta * row; } /* ******************************************************** */ /* Below block put every point value into a link as a curve */ /* ******************************************************** */ // 从这里开始将数据值放入曲线各自对应的链表里 CURVE_DATA *first_node = NULL; CURVE_DATA *data_node = NULL; data_head = first_head; for(num = 0; num < curveNum ; num++) { data_node = new CURVE_DATA; int i = 0; for(i=0; i<16; i++) { data_node->Name[i] = data_head->Name[i]; // 曲线名称 } for(i=0; i<8; i++) { data_node->Unit[i] = data_head->Unit[i]; // 曲线单位 } int startLine = 0; for(row=0; row<lineNum; row++) { if( abs(depth[row]-data_head->startMD)<= delta && depth[row] >= data_head->startMD ) { startLine = row; break; } } // 起始点: startLine wisfile.seekg(data_head->position+2*sizeof(WIS_CHANNEL)+464, std::ios::beg); // 测试样点数: data_head->pointNum for(row=0; row<lineNum; row++) { float data[1]; data[0] = -9999.000; if(row>=startLine && (row-startLine) < data_head->pointNum) { wisfile.read(reinterpret_cast<char *>(&data), sizeof(float)); data_node->Depth[row] = data_head->startMD + delta * (row-startLine); data_node->Value[row] = data[0]; } else { data_node->Depth[row] = minDepth + delta * row; data_node->Value[row] = -9999.000; } // 读取值:data_node->Value[row] } data_node->next = first_node; first_node = data_node; if(data_head->next == NULL) { break; } data_head = data_head->next; } /* **************************************************** */ /* Below block print all point value for every curve */ /* The important thing is how to decide the right depth */ /* **************************************************** */ // 从这里开始写入文本 // Print Curve Name txtfile << std::left << std::setw(12) << "DEPTH"; for(data_node=first_node; data_node!=NULL; data_node=data_node->next) { txtfile << std::left << std::setw(12) << data_node->Name; // txtfile << " "; } txtfile << "/n"; // Print Curve Unit txtfile << std::left << std::setw(12) << "M"; for(data_node=first_node; data_node!=NULL; data_node=data_node->next) { txtfile << std::left << std::setw(12) << data_node->Unit; } txtfile << "/n"; // Print curve value for(row=0; row<lineNum; row++) { if(depth[row] > maxDepth) { break; } txtfile << std::left << std::setw(12) << std::setiosflags(std::ios::fixed) << std::setprecision(3) << depth[row]; // txtfile << " "; for(data_node=first_node; data_node!=NULL; data_node=data_node->next) { txtfile << std::left << std::setw(12) << std::setiosflags(std::ios::fixed) << std::setprecision(3) << data_node->Value[row]; } txtfile << "/n"; } // */ // Process Over wisfile.close(); txtfile.close(); std::cout << infilename << " Complete!" << std::endl; // system("PAUSE"); // Program Over return 0; } </textarea>