C/C++實現(xiàn)segy文件的讀取詳解
本文檔將介紹SEGY的讀取與寫入過程,其中包括IBM與PC兩種數(shù)據(jù)格式的轉(zhuǎn)換。
程序?qū)⒄{(diào)用IEEE2IBM.cpp文件完成IBM與PC格式的互相轉(zhuǎn)換。
新建頭文件ReadSeismic.h與C++文件ReadSeismic.cpp,以及主程序main.cpp。
1 頭文件ReadSeismic.h的編寫及其規(guī)范
1.1 程序描述、調(diào)用、聲明、定義
/********************************************************************** * Copyright(C) 2018,Company All Rights Reserved (1)版權說明 * * @file : ReadSeismic.cpp (2) 文件名 * * @brief : 實現(xiàn)地震數(shù)據(jù)的讀、寫操作 (3) 該文件主要功能簡介 * * @version : 1.0 (4) 版本信息 * * @author : Fan XinRan (5) 創(chuàng)建作者 * * @date : 2022/2/8 星期二 (6) 創(chuàng)建時間 * * Others : (7) 備注、改動信息等 **********************************************************************/ //調(diào)用需要的C頭文件 #include<stdio.h> //C Language header file #include<stdlib.h> #include<string.h> #include<math.h> //調(diào)用需要的C++頭文件 #include<iostream> // C++ header file #include<vector> #include<algorithm> //調(diào)用非標準庫 #include"alloc.h" // 用于創(chuàng)建多維數(shù)組 #include"segy.h" // 包含segy與bhed結構體,用于提取卷頭和道頭中采集、存儲的信息 // 定義全局變量及命名空間 #define PI 3.141592654 //Constant Number Definition #define EPS 0.0000001 using namespace std;
1.2 聲明函數(shù)
unsigned short exchangeLowHigh16(unsigned short Data_temp);//16位高低位轉(zhuǎn)換函數(shù) short占2字節(jié),2*8 unsigned int exchangeLowHigh32(unsigned int Data_temp); //32位高低位轉(zhuǎn)換函數(shù) 4*8 float ibm2pc(unsigned int Data_temp); //IBM轉(zhuǎn)PC數(shù)據(jù) unsigned int pc2ibm(float input); //PC轉(zhuǎn)IBM數(shù)據(jù) float ieee2pc(unsigned int Data_temp); //IEEE轉(zhuǎn)為PC void trace_ibm2pc(float *data_output, int *data_input, int nt); //地震道數(shù)據(jù)由IBM轉(zhuǎn)換為PC格式 void trace_pc2ibm(float *data_input, int *data_output, int nt); //地震道數(shù)據(jù)由PC轉(zhuǎn)換為IBM格式 bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput); //Copy seismic data from Inputfile to Outputfile
1.3完整代碼
/********************************************************************** * Copyright(C) 2018,Company All Rights Reserved * * @file : ReadSeismic.cpp * * @brief : 實現(xiàn)地震數(shù)據(jù)的讀、寫操作 * * @version : 1.0 * * @author : Fan XinRan * * @date : 2022/2/8 星期二 * * Others : **********************************************************************/ //(1)調(diào)用需要的C頭文件 #include<stdio.h> // C Language header file #include<stdlib.h> #include<string.h> #include<math.h> //(2)調(diào)用需要的C++頭文件 #include<iostream> // C++ header file #include<vector> #include<algorithm> //(3)調(diào)用需要的非標準庫頭文件 #include"alloc.h" // project header file #include"segy.h" #include //(4)定義全局常量 #define PI 3.141592654 // Constant Number Definition #define EPS 0.0000001 //(5)聲明命名空間 using namespace std; //(6)聲明函數(shù)名、輸入、輸出及其類型 unsigned short exchangeLowHigh16(unsigned short Data_temp);//16位高低位轉(zhuǎn)換函數(shù) short占2字節(jié),2*8 unsigned int exchangeLowHigh32(unsigned int Data_temp); //32位高低位轉(zhuǎn)換函數(shù) 4*8 float ibm2pc(unsigned int Data_temp); //IBM轉(zhuǎn)PC數(shù)據(jù) unsigned int pc2ibm(float input); //PC轉(zhuǎn)IBM數(shù)據(jù) float ieee2pc(unsigned int Data_temp); //IEEE轉(zhuǎn)為PC void trace_ibm2pc(float *data_output, int *data_input, int nt); //地震道數(shù)據(jù)由IBM轉(zhuǎn)換為PC格式 void trace_pc2ibm(float *data_input, int *data_output, int nt); //地震道數(shù)據(jù)由PC轉(zhuǎn)換為IBM格式 bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput); //Copy seismic data from Inputfile to Outputfile
2 C++文件ReadSeismic.cpp的編寫及其規(guī)范
2.1 必要的說明
/*************************************************************************************************************
Function: copySeismicDataIBM (1)函數(shù)名
Description: copy segy file from input data to output data (2)簡要描述其功能
Input:
const char *filenameInput [in] input filename (.segy) (3)輸入變量及輸入文件類型
Output:
const char *filenameOutput[out] output filename (.segy) (4)輸出變量及輸出文件類型
Return:
bool true program success
bool false program failed (5)返回值及其說明
Author: Fan XinRan (6)創(chuàng)建作者
Date : 2022/2/8 (7)創(chuàng)建時間
Others: (8)備注、改動信息等
*************************************************************************************************************/
2.2 定義讀、寫函數(shù)
#include "ReadSeismic.h"
bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput){
//實現(xiàn)代碼
...
}
(1)定義待使用的結構體變量、數(shù)值型變量
bhed 與 segy均為定義在segy.h中的結構體(structure),分別包含了二進制卷頭信息與道頭信息,使用成員訪問運算符(.)獲取其內(nèi)容;
使用unsigned int 聲明整型變量,使用long long 或__int64聲明SEGY文件字節(jié)數(shù)、地震道字節(jié)數(shù),防止數(shù)據(jù)量超出范圍,并且盡可能初始化變量。
bhed fileheader; // file header 卷頭 segy traceheader; // trace header 道頭 unsigned int nt=0; // number of sample 采樣點數(shù) unsigned int sizefileheader=sizeof(fileheader); // size of fileheader; unsigned int sizetraceheader=sizeof(traceheader); // size of traceheader; unsigned int ncdp = 0; // number of cdp 道數(shù) long long size_file = 0; //size of input file long long size_trace = 0; //size of per-trace
(2)新建指針變量
在讀、寫地震道數(shù)據(jù)這一任務中,需要用到輸入指針、輸出指針、地震道數(shù)據(jù)指針、道頭指針以及一個臨時指針變量,共五個指針變量。
FILE *fpinput = NULL; // input file pointer FILE *fpoutput = NULL; // output file pointer float *dataInput = NULL; // input data pointer segy *traceheaderArray = NULL; // traceheader pointer int* temp = NULL; // temp pointer
之前的任務中fread(dataInput[itrace],nt * sizeof(float),1,fpinput),
整個讀、寫流程為:fpinput-->讀取nt個數(shù)據(jù)-->dataInput[itrace]-->寫入nt個數(shù)據(jù)-->fpoutput
本次任務中需要對數(shù)據(jù)進行變換,流程變?yōu)椋?code>fpinput-->讀取nt個數(shù)據(jù)-->temp-->IBM/PC轉(zhuǎn)換-->dataInput[itrace]-->寫入nt個數(shù)據(jù)-->fpoutput。
(3)打開輸入、輸出文件指針
fpinput = fopen(filenameInput, "rb"); //open input file pointer
fpoutput = fopen(filenameOutput,"wb"); //open output file pointer
//讀寫操作
...
//fopen()與fclose()成對出現(xiàn),在對文件的操作完成后切記關閉文件
fclose(fpinput); //close input file pointer
fclose(fpoutput); //close output file pointer
(4)判斷文件打開情況
if(fpinput==NULL){ //如果文件指針為NULL
printf("Cannot open %s file\n", filenameInput); //打印“文件打開失敗”
return false; //結束程序
}
if(fpoutput==NULL){
printf("Cannot open %s file\n", filenameOutput);
return false;
}
(5)讀取/計算卷、道信息
fread(&fileheader,sizefileheader,1,fpinput); // 從輸入流(fpinput)中讀取卷頭信息到指定地址---->fileheader nt = exchangeLowHigh16(fileheader.hns) // 高低位轉(zhuǎn)換 _fseeki64(fpinput,0,SEEK_END); // 從文件末尾偏移這個結構體0個長度給文件指針fpinput,即fpinput此時指向文件尾 size_file = _ftelli64(fpinput); // 返回當前文件位置,即文件總字節(jié)數(shù) size_trace = nt*sizeof(float)+sizetraceheader; // 每一道的字節(jié)數(shù) = 采樣點字節(jié)數(shù)+道頭字節(jié)數(shù) ncdp = (size_file - (long long)sizefileheader)/size_trace; // 道數(shù) = (文件總字節(jié)數(shù) - 卷頭字節(jié)數(shù))/每一道的字節(jié)數(shù) _fseeki64(fpinput,sizefileheader,SEEK_SET); // 從文件開頭偏移sizefileheader(卷頭字節(jié)數(shù))個長度給指針fpinput,即fpinput此時指向第一道的開始 fwrite(&fileheader, sizefileheader, 1, fpoutput); // 先寫入卷頭
fread()從給定流讀取數(shù)據(jù)到指針所指向的數(shù)組中;fwrite(*ptr, size, nmemb,*stream)參數(shù)與fread()相同,把ptr所指向的數(shù)組中的數(shù)據(jù)寫入到給定流stream中;_fseeki64的用法與fseek相同,表示從文件指定位置偏移一定字節(jié)數(shù);前者具有更高的兼容性;_ftelli64與ftell同理,返回給定流的當前文件位置;exchangeLowHigh16()完成short型的高低位轉(zhuǎn)換,int型的高低位轉(zhuǎn)換使用exchangeLowHigh64()。
(6)遍歷每一條地震道,讀、寫數(shù)據(jù)
dataInput=alloc2float(nt,ncdp); // 分配nt*ncdp(采樣點數(shù)×道數(shù))所需的內(nèi)存空間,用來存放二維地震道數(shù)據(jù)
//其中,alloc2float是卸載alloc.h中的函數(shù),創(chuàng)建一個float型的二維數(shù)組
//dataInput為二級指針,可簡記為dataInput指向每一行的開頭
memset(dataInput[0], 0, nt*ncdp * sizeof(float)); // 從第一行的開頭開始,將內(nèi)存塊中nt*ncdp個字符賦值為0
// dataInput指向每行開頭,而dataInput[0]則為整個二維數(shù)組的起始位置
// 在內(nèi)存的動態(tài)存儲區(qū)中分配ncdp個長度為sizetraceheader的連續(xù)空間
traceheaderArray = (segy*)calloc(ncdp,sizetraceheader);
temp = (int*)calloc(nt,sizeof(int));
//逐道讀取道頭與地震道數(shù)據(jù)
for(int itrace = 0; itrace < ncdp; itrace++){
fread(&traceheaderArray[itrace],sizetraceheader,1,fpinput); // &traceheaderArray[itrace]為第itrace道的地址,讀取該道頭信息
fread(temp,nt * sizeof(float),1,fpinput); // 讀取nt個采樣點的信息并將結果指向temp
// 使用trace_ibm2pc將temp位置后nt個采樣點的數(shù)據(jù),進行IBM-->PC的轉(zhuǎn)換,結果指向每一道開頭(dataInput[itrace])
trace_ibm2pc(dataInput[itrace], temp, nt);
}//end for(int itrace = 0; itrace < ncdp; itrace++)
//逐道寫入道頭與地震道數(shù)據(jù)
for (int itrace = 0; itrace < ncdp; itrace++) {
fwrite(&traceheaderArray[itrace], sizetraceheader, 1, fpoutput); // 寫入該道頭信息
// 使用trace_pc2ibm將temp位置后nt個采樣點的數(shù)據(jù),進行PC-->IBM的轉(zhuǎn)換,結果指向每一道開頭(dataInput[itrace])
trace_pc2ibm(dataInput[itrace],temp,nt);
fwrite(temp, nt * sizeof(int), 1, fpoutput); // 以IBM的格式存回fpoutput
}//end for(int itrace = 0; itrace < ncdp; itrace++)
// 在每個循環(huán)末尾的"}"添加備注,便于尋找和區(qū)分
//在寫操作完成后釋放內(nèi)存
free(temp); // free temp pointer
free(traceheaderArray); // free traceheader pointer
free2float(dataInput); // free data input pointer
calloc(num,size):在內(nèi)存的動態(tài)存儲區(qū)中分配num個長度為size的連續(xù)空間,函數(shù)返回一個指向分配起始地址的指針;如果分配不成功,返回NULL;malloc(size):功能與calloc()相似,不同之處是malloc()不會將內(nèi)存值初始化為0,而calloc()會將新申請的內(nèi)存填充0。
2.3完整代碼
/*****************************************************************************
Function: CopySeismicData
Description: copy segy file from input data to output data
Input:
const char *filenameInput [in] input filename (.segy)
Output:
const char *filenameOutput[out] output filename (.segy)
Return:
bool true program success
bool false program failed
Author: Fan XinRan
Date : 2022/2/8
Others:
*****************************************************************************/
#include "ReadSeismic.h"
bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput){
segy traceheader; // trace header
bhed fileheader; // file header
unsigned int nt = 0; // number of sample
unsigned int sizetraceheader = sizeof(traceheader); // size of traceheader;
unsigned int sizefileheader = sizeof(fileheader); // size of fileheader;
unsigned int ncdp = 0; // number of cdp
long long size_file = 0; //size of input file
long long size_trace = 0; //size of per-trace
FILE *fpinput = NULL; // input file pointer
FILE *fpoutput = NULL; //output file pointer
float **dataInput = NULL; //input data pointer
segy *traceheaderArray = NULL; //
int* temp = NULL;
fpinput = fopen(filenameInput, "rb"); //open input file pointer
fpoutput = fopen(filenameOutput, "wb"); //open output file pointer
if (fpinput == NULL) {
printf("Cannot open %s file\n", filenameInput);
return false;
}
if (fpoutput == NULL) {
printf("Cannot open %s file\n", filenameOutput);
return false;
}
fread(&fileheader, sizefileheader, 1, fpinput);
nt = fileheader.hns;
nt = exchangeLowHigh16(fileheader.hns);
_fseeki64(fpinput, 0, SEEK_END);
size_file = _ftelli64(fpinput);
size_trace = nt * sizeof(float) + sizetraceheader;
ncdp = (size_file - (long long)sizefileheader) / size_trace;
_fseeki64(fpinput, sizefileheader, SEEK_SET);
dataInput = alloc2float(nt, ncdp);
memset(dataInput[0], 0, nt*ncdp * sizeof(float));
traceheaderArray = (segy*)calloc(ncdp, sizetraceheader);
temp = (int*)calloc(nt,sizeof(int));
fwrite(&fileheader,sizefileheader,1, fpoutput);
for (int itrace = 0; itrace < ncdp; itrace++) {
fread(&traceheaderArray[itrace], sizetraceheader, 1, fpinput);
fread(temp, nt * sizeof(int), 1, fpinput);
trace_ibm2pc(dataInput[itrace], temp, nt);
}//end for(int itrace = 0; itrace < ncdp; itrace++)
for (int itrace = 0; itrace < ncdp; itrace++) {
fwrite(&traceheaderArray[itrace], sizetraceheader, 1, fpoutput);
trace_pc2ibm(dataInput[itrace],temp,nt);
fwrite(temp, nt * sizeof(int), 1, fpoutput);
}//end for(int itrace = 0; itrace < ncdp; itrace++)
free(temp);
free(traceheaderArray);
free2float(dataInput); // free data input pointer
fclose(fpoutput); //close output file pointer
fclose(fpinput); //close input file pointer
return true;
}
3 主函數(shù)main.cpp及運行結果
#include"ReadSeismic.h"
void main(){
copySeismicDataIBM("Azi6-Ang35-BZ19-6-1.segy","Outputibm.segy");
}
運行主函數(shù)后,程序會讀入Azi6-Ang35-BZ19-6-1.segy,這是一個IBM格式的數(shù)據(jù)。再寫入到Outputibm.segy,從而完成對SEGY文件的復制。
以上就是C/C++實現(xiàn)segy文件的讀取詳解的詳細內(nèi)容,更多關于C++讀取segy文件的資料請關注腳本之家其它相關文章!

