SEGY IO (IBM&PC)

本文档将介绍SEGY的读取与写入过程,其中包括IBMPC两种数据格式的转换。

程序将调用IEEE2IBM.cpp文件完成IBM与PC格式的互相转换。

新建头文件ReadSeismic.h与C++文件ReadSeismic.cpp,以及主程序main.cpp

1 头文件ReadSeismic.h的编写及其规范

1.1 程序描述、调用、声明、定义

  1. /**********************************************************************
  2. * Copyright(C) 2018,Company All Rights Reserved (1)版权说明
  3. *
  4. * @file : ReadSeismic.cpp (2) 文件名
  5. *
  6. * @brief : 实现地震数据的读、写操作 (3) 该文件主要功能简介
  7. *
  8. * @version : 1.0 (4) 版本信息
  9. *
  10. * @author : Fan XinRan (5) 创建作者
  11. *
  12. * @date : 2022/2/8 星期二 (6) 创建时间
  13. *
  14. * Others : (7) 备注、改动信息等
  15. **********************************************************************/
  16. //调用需要的C头文件
  17. #include<stdio.h> //C Language header file
  18. #include<stdlib.h>
  19. #include<string.h>
  20. #include<math.h>
  21. //调用需要的C++头文件
  22. #include<iostream> // C++ header file
  23. #include<vector>
  24. #include<algorithm>
  25. //调用非标准库
  26. #include"alloc.h" // 用于创建多维数组
  27. #include"segy.h" // 包含segy与bhed结构体,用于提取卷头和道头中采集、存储的信息
  28. // 定义全局变量及命名空间
  29. #define PI 3.141592654 //Constant Number Definition
  30. #define EPS 0.0000001
  31. using namespace std;

1.2 声明函数

  1. unsigned short exchangeLowHigh16(unsigned short Data_temp);//16位高低位转换函数 short占2字节,2*8
  2. unsigned int exchangeLowHigh32(unsigned int Data_temp); //32位高低位转换函数 4*8
  3. float ibm2pc(unsigned int Data_temp); //IBM转PC数据
  4. unsigned int pc2ibm(float input); //PC转IBM数据
  5. float ieee2pc(unsigned int Data_temp); //IEEE转为PC
  6. void trace_ibm2pc(float *data_output, int *data_input, int nt); //地震道数据由IBM转换为PC格式
  7. void trace_pc2ibm(float *data_input, int *data_output, int nt); //地震道数据由PC转换为IBM格式
  8. bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput); //Copy seismic data from Inputfile to Outputfile

完整代码

  1. /**********************************************************************
  2. * Copyright(C) 2018,Company All Rights Reserved
  3. *
  4. * @file : ReadSeismic.cpp
  5. *
  6. * @brief : 实现地震数据的读、写操作
  7. *
  8. * @version : 1.0
  9. *
  10. * @author : Fan XinRan
  11. *
  12. * @date : 2022/2/8 星期二
  13. *
  14. * Others :
  15. **********************************************************************/
  16. //(1)调用需要的C头文件
  17. #include<stdio.h> // C Language header file
  18. #include<stdlib.h>
  19. #include<string.h>
  20. #include<math.h>
  21. //(2)调用需要的C++头文件
  22. #include<iostream> // C++ header file
  23. #include<vector>
  24. #include<algorithm>
  25. //(3)调用需要的非标准库头文件
  26. #include"alloc.h" // project header file
  27. #include"segy.h"
  28. #include
  29. //(4)定义全局常量
  30. #define PI 3.141592654 // Constant Number Definition
  31. #define EPS 0.0000001
  32. //(5)声明命名空间
  33. using namespace std;
  34. //(6)声明函数名、输入、输出及其类型
  35. unsigned short exchangeLowHigh16(unsigned short Data_temp);//16位高低位转换函数 short占2字节,2*8
  36. unsigned int exchangeLowHigh32(unsigned int Data_temp); //32位高低位转换函数 4*8
  37. float ibm2pc(unsigned int Data_temp); //IBM转PC数据
  38. unsigned int pc2ibm(float input); //PC转IBM数据
  39. float ieee2pc(unsigned int Data_temp); //IEEE转为PC
  40. void trace_ibm2pc(float *data_output, int *data_input, int nt); //地震道数据由IBM转换为PC格式
  41. void trace_pc2ibm(float *data_input, int *data_output, int nt); //地震道数据由PC转换为IBM格式
  42. bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput); //Copy seismic data from Inputfile to Outputfile

2 C++文件ReadSeismic.cpp的编写及其规范

2.1 必要的说明

  1. /*************************************************************************************************************
  2. Function: copySeismicDataIBM (1)函数名
  3. Description: copy segy file from input data to output data (2)简要描述其功能
  4. Input:
  5. const char *filenameInput [in] input filename (.segy) (3)输入变量及输入文件类型
  6. Output:
  7. const char *filenameOutput[out] output filename (.segy) (4)输出变量及输出文件类型
  8. Return:
  9. bool true program success
  10. bool false program failed (5)返回值及其说明
  11. Author: Fan XinRan (6)创建作者
  12. Date : 2022/2/8 (7)创建时间
  13. Others: (8)备注、改动信息等
  14. *************************************************************************************************************/

2.2 定义读、写函数

  1. #include "ReadSeismic.h"
  2. bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput){
  3. //实现代码
  4. ...
  5. }

(1)定义待使用的结构体变量、数值型变量

bhedsegy均为定义在segy.h中的结构体(structure),分别包含了二进制卷头信息与道头信息,使用成员访问运算符(.)获取其内容;

使用unsigned int 声明整型变量,使用long long__int64声明SEGY文件字节数、地震道字节数,防止数据量超出范围,并且尽可能初始化变量。

  1. bhed fileheader; // file header 卷头
  2. segy traceheader; // trace header 道头
  3. unsigned int nt=0; // number of sample 采样点数
  4. unsigned int sizefileheader=sizeof(fileheader); // size of fileheader;
  5. unsigned int sizetraceheader=sizeof(traceheader); // size of traceheader;
  6. unsigned int ncdp = 0; // number of cdp 道数
  7. long long size_file = 0; //size of input file
  8. long long size_trace = 0; //size of per-trace

(2)新建指针变量

在读、写地震道数据这一任务中,需要用到输入指针、输出指针、地震道数据指针、道头指针以及一个临时指针变量,共五个指针变量。

  1. FILE *fpinput = NULL; // input file pointer
  2. FILE *fpoutput = NULL; // output file pointer
  3. float *dataInput = NULL; // input data pointer
  4. segy *traceheaderArray = NULL; // traceheader pointer
  5. int* temp = NULL; // temp pointer

之前的任务中fread(dataInput[itrace],nt * sizeof(float),1,fpinput)

整个读、写流程为:fpinput-->读取nt个数据-->dataInput[itrace]-->写入nt个数据-->fpoutput

本次任务中需要对数据进行变换,流程变为:fpinput-->读取nt个数据-->temp-->IBM/PC转换-->dataInput[itrace]-->写入nt个数据-->fpoutput

(3)打开输入、输出文件指针

  1. fpinput = fopen(filenameInput, "rb"); //open input file pointer
  2. fpoutput = fopen(filenameOutput,"wb"); //open output file pointer
  3. //读写操作
  4. ...
  5. //fopen()与fclose()成对出现,在对文件的操作完成后切记关闭文件
  6. fclose(fpinput); //close input file pointer
  7. fclose(fpoutput); //close output file pointer

(4)判断文件打开情况

  1. if(fpinput==NULL){ //如果文件指针为NULL
  2. printf("Cannot open %s file\n", filenameInput); //打印“文件打开失败”
  3. return false; //结束程序
  4. }
  5. if(fpoutput==NULL){
  6. printf("Cannot open %s file\n", filenameOutput);
  7. return false;
  8. }

(5)读取/计算卷、道信息

  1. fread(&fileheader,sizefileheader,1,fpinput); // 从输入流(fpinput)中读取卷头信息到指定地址---->fileheader
  2. nt = exchangeLowHigh16(fileheader.hns) // 高低位转换
  3. _fseeki64(fpinput,0,SEEK_END); // 从文件末尾偏移这个结构体0个长度给文件指针fpinput,即fpinput此时指向文件尾
  4. size_file = _ftelli64(fpinput); // 返回当前文件位置,即文件总字节数
  5. size_trace = nt*sizeof(float)+sizetraceheader; // 每一道的字节数 = 采样点字节数+道头字节数
  6. ncdp = (size_file - (long long)sizefileheader)/size_trace; // 道数 = (文件总字节数 - 卷头字节数)/每一道的字节数
  7. _fseeki64(fpinput,sizefileheader,SEEK_SET); // 从文件开头偏移sizefileheader(卷头字节数)个长度给指针fpinput,即fpinput此时指向第一道的开始
  8. fwrite(&fileheader, sizefileheader, 1, fpoutput); // 先写入卷头
  1. fread() 从给定流读取数据到指针所指向的数组中;
  2. fwrite(*ptr, size, nmemb,*stream) 参数与fread()相同,把ptr所指向的数组中的数据写入到给定流stream中;
  3. _fseeki64的用法与fseek相同,表示从文件指定位置偏移一定字节数;前者具有更高的兼容性;
  4. _ftelli64ftell同理,返回给定流的当前文件位置;
  5. exchangeLowHigh16()完成short型的高低位转换,int型的高低位转换使用exchangeLowHigh64()

(6)遍历每一条地震道,读、写数据

  1. dataInput=alloc2float(nt,ncdp); // 分配nt*ncdp(采样点数×道数)所需的内存空间,用来存放二维地震道数据
  2. //其中,alloc2float是卸载alloc.h中的函数,创建一个float型的二维数组
  3. //dataInput为二级指针,可简记为dataInput指向每一行的开头
  4. memset(dataInput[0], 0, nt*ncdp * sizeof(float)); // 从第一行的开头开始,将内存块中nt*ncdp个字符赋值为0
  5. // dataInput指向每行开头,而dataInput[0]则为整个二维数组的起始位置
  6. // 在内存的动态存储区中分配ncdp个长度为sizetraceheader的连续空间
  7. traceheaderArray = (segy*)calloc(ncdp,sizetraceheader);
  8. temp = (int*)calloc(nt,sizeof(int));
  9. //逐道读取道头与地震道数据
  10. for(int itrace = 0; itrace < ncdp; itrace++){
  11. fread(&traceheaderArray[itrace],sizetraceheader,1,fpinput); // &traceheaderArray[itrace]为第itrace道的地址,读取该道头信息
  12. fread(temp,nt * sizeof(float),1,fpinput); // 读取nt个采样点的信息并将结果指向temp
  13. // 使用trace_ibm2pc将temp位置后nt个采样点的数据,进行IBM-->PC的转换,结果指向每一道开头(dataInput[itrace])
  14. trace_ibm2pc(dataInput[itrace], temp, nt);
  15. }//end for(int itrace = 0; itrace < ncdp; itrace++)
  16. //逐道写入道头与地震道数据
  17. for (int itrace = 0; itrace < ncdp; itrace++) {
  18. fwrite(&traceheaderArray[itrace], sizetraceheader, 1, fpoutput); // 写入该道头信息
  19. // 使用trace_pc2ibm将temp位置后nt个采样点的数据,进行PC-->IBM的转换,结果指向每一道开头(dataInput[itrace])
  20. trace_pc2ibm(dataInput[itrace],temp,nt);
  21. fwrite(temp, nt * sizeof(int), 1, fpoutput); // 以IBM的格式存回fpoutput
  22. }//end for(int itrace = 0; itrace < ncdp; itrace++)
  23. // 在每个循环末尾的"}"添加备注,便于寻找和区分
  24. //在写操作完成后释放内存
  25. free(temp); // free temp pointer
  26. free(traceheaderArray); // free traceheader pointer
  27. free2float(dataInput); // free data input pointer
  1. calloc(num,size):在内存的动态存储区中分配num个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL;
  2. malloc(size):功能与calloc() 相似,不同之处是malloc() 不会将内存值初始化为0,而 calloc()会将新申请的内存填充0。

完整代码

  1. /*****************************************************************************
  2. Function: CopySeismicData
  3. Description: copy segy file from input data to output data
  4. Input:
  5. const char *filenameInput [in] input filename (.segy)
  6. Output:
  7. const char *filenameOutput[out] output filename (.segy)
  8. Return:
  9. bool true program success
  10. bool false program failed
  11. Author: Fan XinRan
  12. Date : 2022/2/8
  13. Others:
  14. *****************************************************************************/
  15. #include "ReadSeismic.h"
  16. bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput){
  17. segy traceheader; // trace header
  18. bhed fileheader; // file header
  19. unsigned int nt = 0; // number of sample
  20. unsigned int sizetraceheader = sizeof(traceheader); // size of traceheader;
  21. unsigned int sizefileheader = sizeof(fileheader); // size of fileheader;
  22. unsigned int ncdp = 0; // number of cdp
  23. long long size_file = 0; //size of input file
  24. long long size_trace = 0; //size of per-trace
  25. FILE *fpinput = NULL; // input file pointer
  26. FILE *fpoutput = NULL; //output file pointer
  27. float **dataInput = NULL; //input data pointer
  28. segy *traceheaderArray = NULL; //
  29. int* temp = NULL;
  30. fpinput = fopen(filenameInput, "rb"); //open input file pointer
  31. fpoutput = fopen(filenameOutput, "wb"); //open output file pointer
  32. if (fpinput == NULL) {
  33. printf("Cannot open %s file\n", filenameInput);
  34. return false;
  35. }
  36. if (fpoutput == NULL) {
  37. printf("Cannot open %s file\n", filenameOutput);
  38. return false;
  39. }
  40. fread(&fileheader, sizefileheader, 1, fpinput);
  41. nt = fileheader.hns;
  42. nt = exchangeLowHigh16(fileheader.hns);
  43. _fseeki64(fpinput, 0, SEEK_END);
  44. size_file = _ftelli64(fpinput);
  45. size_trace = nt * sizeof(float) + sizetraceheader;
  46. ncdp = (size_file - (long long)sizefileheader) / size_trace;
  47. _fseeki64(fpinput, sizefileheader, SEEK_SET);
  48. dataInput = alloc2float(nt, ncdp);
  49. memset(dataInput[0], 0, nt*ncdp * sizeof(float));
  50. traceheaderArray = (segy*)calloc(ncdp, sizetraceheader);
  51. temp = (int*)calloc(nt,sizeof(int));
  52. fwrite(&fileheader,sizefileheader,1, fpoutput);
  53. for (int itrace = 0; itrace < ncdp; itrace++) {
  54. fread(&traceheaderArray[itrace], sizetraceheader, 1, fpinput);
  55. fread(temp, nt * sizeof(int), 1, fpinput);
  56. trace_ibm2pc(dataInput[itrace], temp, nt);
  57. }//end for(int itrace = 0; itrace < ncdp; itrace++)
  58. for (int itrace = 0; itrace < ncdp; itrace++) {
  59. fwrite(&traceheaderArray[itrace], sizetraceheader, 1, fpoutput);
  60. trace_pc2ibm(dataInput[itrace],temp,nt);
  61. fwrite(temp, nt * sizeof(int), 1, fpoutput);
  62. }//end for(int itrace = 0; itrace < ncdp; itrace++)
  63. free(temp);
  64. free(traceheaderArray);
  65. free2float(dataInput); // free data input pointer
  66. fclose(fpoutput); //close output file pointer
  67. fclose(fpinput); //close input file pointer
  68. return true;
  69. }

3 主函数main.cpp及运行结果

  1. #include"ReadSeismic.h"
  2. void main(){
  3. copySeismicDataIBM("Azi6-Ang35-BZ19-6-1.segy","Outputibm.segy");
  4. }

运行主函数后,程序会读入Azi6-Ang35-BZ19-6-1.segy,这是一个IBM格式的数据。再写入到Outputibm.segy,从而完成对SEGY文件的复制。

C/C++读取SEGY文件(三)的更多相关文章

  1. C/C++语言读取SEGY文件笔记(一)

    SEGY IO 推荐采用的IDE为Visual studio(VS),本文档将介绍SEGY文件的读取与写入过程,即SEGY文件的复制. 因此,新建头文件ReadSeismic.h与C++文件ReadS ...

  2. C/C++语言读取SEGY文件(二)

    SEGY IO (2D) 本文档将介绍SEGY的读取与写入过程,即SEGY文件的复制,并且在实现过程采用采样点×道数二维数组的形式读写. 新建头文件SegyDataIO2D.h与C++文件SegyDa ...

  3. sas通过IMPORT过程读取外部文件数据

    SAS通过IMPORT过程读取外部文件数据 使用IMPORT过程导入带分隔符的文件外,Microsoft Access数据库文件.Miscrosft Excel工作簿. dBase文件.JMP文件.S ...

  4. C# 读取EXCEL文件的三种经典方法

    1.方法一:采用OleDB读取EXCEL文件: 把EXCEL文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(string Path) { stri ...

  5. ASP.NET读取EXCEL文件的三种经典方法(转)

    1.方法一:采用OleDB读取EXCEL文件:  把EXCEL文件当做一个数据源来进行数据的读取操作,实例如下:public DataSet ExcelToDS(string Path) {  str ...

  6. ASP.NET读取EXCEL文件的三种经典方法

      1.方法一:采用OleDB读取EXCEL文件:   把EXCEL文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(string Path) { ...

  7. (转)C# 读取EXCEL文件的三种经典方法

    原文地址http://www.open-open.com/code/view/1420029490093 1.方法一:采用OleDB读取EXCEL文件: 把EXCEL文件当做一个数据源来进行数据的读取 ...

  8. .NET读取Excel文件的三种方法的区别

    ASP.NET读取Excel文件方法一:采用OleDB读取Excel文件: 把Excel文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(strin ...

  9. 转:C# 读取EXCEL文件的三种经典方法

    1.方法一:采用OleDB读取EXCEL文件: 把EXCEL文件当做一个数据源来进行数据的读取操作,实例如下: public DataSet ExcelToDS(string Path) { stri ...

随机推荐

  1. CentOs7.6配置邮件服务并发送邮件

    1.使用Yum 来安装依赖包 yum -y install sendmail yum -y install mailx 2.获取授权码 下面以腾讯为例 https://service.mail.qq. ...

  2. 控制器view生命周期

    控制器View的生命周期方法:只要是控制器的生命周期方法,都是以view开头. 控制器View加载完成时调用- (void)viewDidLoad { [super viewDidLoad];} 控制 ...

  3. java中的成员变量和局部变量的区别

    成员变量: 在类体里面定义的变量叫做成员变量: 如果在变量有static关键字修饰,就叫作静态变量或类变量: 如果该变量没有static关键字修饰,就叫作非静态变量或实例变量: 局部变量: 方法内定义 ...

  4. play的action链(一个action跳转到另一个action,类似于重定向)

    在play中没有Servlet API forward 的等价物.每一个HTTP request只能调用一个action.如果我们需要调用另一个,必须通过重定向,让浏览器访问另一个URL来访问它.这样 ...

  5. iOS中处理时间的类

      登录|注册     sakulafly的专栏       目录视图 摘要视图 订阅 Markdown博文大赛清新开启    天天爱答题 一大波C币袭来    中国云计算大会演讲议题公布     大 ...

  6. 微服务如何聚合 API 文档?这波秀~

    今天这篇文章介绍一下微服务如何聚合Swagger实现接口文档管理. 文章目录如下: 为什么需要聚合? 微服务模块众多,如果不聚合文档,则访问每个服务的API文档都需要单独访问一个Swagger UI界 ...

  7. [USACO4.2]工序安排Job Processing

    两种想法: (样例是真的良心,卡掉了两种错误做法)洗完一件马上塞一件到最快的空闲烘干机去?X,因为最后一件洗完的衣服决定了第二问的答案,但它并不一定得到最优待遇--最快的烘干机.   给最后一件洗完的 ...

  8. Solution -「六省联考 2017」「洛谷 P3750」分手是祝愿

    \(\mathcal{Description}\)   Link.   有 \(n\) 盏编号为 \(1\sim n\),已知初始状态的灯,每次操作选取 \(x\in[1,n]\),使得所有编号为 \ ...

  9. Note -「Mobius 反演」光速入门

    目录 Preface 数论函数 积性函数 Dirichlet 卷积 Dirichlet 卷积中的特殊函数 Mobius 函数 & Mobius 反演 Mobius 函数 Mobius 反演 基 ...

  10. WebKit Inside: DOM树的构建

    当客户端App主进程创建WKWebView对象时,会创建另外两个子进程:渲染进程与网络进程.主进程WKWebView发起请求时,先将请求转发给渲染进程,渲染进程再转发给网络进程,网络进程请求服务器.如 ...