C/C++实现segy文件的读取详解

目录
  • 1头文件ReadSeismic.h的编写及其规范
    • 1.1程序描述、调用、声明、定义
    • 1.2声明函数
    • 1.3完整代码
  • 2C++文件ReadSeismic.cpp的编写及其规范
    • 2.1必要的说明
    • 2.2定义读、写函数
    • 2.3完整代码
  • 3主函数main.cpp及运行结果

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

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

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

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

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

/**********************************************************************

 * Copyright(C) 2018,Company All Rights Reserved   (1)版权说明
   *
 * @file    : ReadSeismic.cpp                      (2) 文件名
   *
 * @brief   :  实现地震数据的读、写操作                 (3) 该文件主要功能简介
   *
 * @version : 1.0                                  (4) 版本信息
   *
 * @author  : Fan XinRan                           (5) 创建作者
   *
 * @date    : 2022/2/8 星期二                       (6) 创建时间
   *
 * Others  :                                       (7) 备注、改动信息等
   **********************************************************************/

//调用需要的C头文件
#include<stdio.h>   //C Language header file
#include<stdlib.h>
#include<string.h>
#include<math.h>

//调用需要的C++头文件
#include<iostream>  // C++ header file
#include<vector>
#include<algorithm>

//调用非标准库
#include"alloc.h"   // 用于创建多维数组
#include"segy.h"   // 包含segy与bhed结构体,用于提取卷头和道头中采集、存储的信息

// 定义全局变量及命名空间
#define PI 3.141592654   //Constant Number Definition
#define EPS 0.0000001

using namespace std;

1.2 声明函数

unsigned short exchangeLowHigh16(unsigned short Data_temp);//16位高低位转换函数  short占2字节,2*8
unsigned int exchangeLowHigh32(unsigned int Data_temp); //32位高低位转换函数  4*8
float ibm2pc(unsigned int Data_temp);      //IBM转PC数据
unsigned int pc2ibm(float input);          //PC转IBM数据
float ieee2pc(unsigned int Data_temp);   //IEEE转为PC

void trace_ibm2pc(float *data_output, int *data_input, int nt); //地震道数据由IBM转换为PC格式
void trace_pc2ibm(float *data_input, int *data_output, int nt); //地震道数据由PC转换为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   :  实现地震数据的读、写操作
   *
 * @version : 1.0
   *
 * @author  : Fan XinRan
   *
 * @date    : 2022/2/8 星期二
   *
 * Others  :
   **********************************************************************/

//(1)调用需要的C头文件
#include<stdio.h>   // C Language header file
#include<stdlib.h>
#include<string.h>
#include<math.h>

//(2)调用需要的C++头文件
#include<iostream>  // C++ header file
#include<vector>
#include<algorithm>

//(3)调用需要的非标准库头文件
#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)声明函数名、输入、输出及其类型
unsigned short exchangeLowHigh16(unsigned short Data_temp);//16位高低位转换函数  short占2字节,2*8
unsigned int exchangeLowHigh32(unsigned int Data_temp); //32位高低位转换函数  4*8
float ibm2pc(unsigned int Data_temp);      //IBM转PC数据
unsigned int pc2ibm(float input);          //PC转IBM数据
float ieee2pc(unsigned int Data_temp);   //IEEE转为PC

void trace_ibm2pc(float *data_output, int *data_input, int nt); //地震道数据由IBM转换为PC格式
void trace_pc2ibm(float *data_input, int *data_output, int nt); //地震道数据由PC转换为IBM格式

bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput); //Copy seismic data from Inputfile to Outputfile

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

2.1 必要的说明

/*************************************************************************************************************

 Function:       copySeismicDataIBM                                                (1)函数名
 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)创建作者
 Date  :     2022/2/8                                                              (7)创建时间
 Others:                                                                           (8)备注、改动信息等

*************************************************************************************************************/

2.2 定义读、写函数

#include "ReadSeismic.h"
bool copySeismicDataIBM(const char *filenameInput, const char *filenameOutput){

    //实现代码
    ...

}

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

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

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

bhed fileheader;        // file header  卷头
segy traceheader;       // trace header  道头
unsigned int nt=0;        // number of sample  采样点数
unsigned int sizefileheader=sizeof(fileheader);   // size of fileheader;
unsigned int sizetraceheader=sizeof(traceheader);  // size of traceheader;

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

(2)新建指针变量

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

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个数据-->dataInput[itrace]-->写入nt个数据-->fpoutput

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

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

fpinput = fopen(filenameInput, "rb");  //open input file pointer
fpoutput = fopen(filenameOutput,"wb");  //open output file pointer

//读写操作
...

//fopen()与fclose()成对出现,在对文件的操作完成后切记关闭文件
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) // 高低位转换

_fseeki64(fpinput,0,SEEK_END);   // 从文件末尾偏移这个结构体0个长度给文件指针fpinput,即fpinput此时指向文件尾

size_file = _ftelli64(fpinput);  // 返回当前文件位置,即文件总字节数
size_trace = nt*sizeof(float)+sizetraceheader;  // 每一道的字节数 = 采样点字节数+道头字节数

ncdp = (size_file - (long long)sizefileheader)/size_trace; // 道数 = (文件总字节数 - 卷头字节数)/每一道的字节数

_fseeki64(fpinput,sizefileheader,SEEK_SET); // 从文件开头偏移sizefileheader(卷头字节数)个长度给指针fpinput,即fpinput此时指向第一道的开始
fwrite(&fileheader, sizefileheader, 1, fpoutput); // 先写入卷头
  • fread() 从给定流读取数据到指针所指向的数组中;
  • fwrite(*ptr, size, nmemb,*stream) 参数与fread()相同,把ptr所指向的数组中的数据写入到给定流stream中;
  • _fseeki64的用法与fseek相同,表示从文件指定位置偏移一定字节数;前者具有更高的兼容性;
  • _ftelli64ftell同理,返回给定流的当前文件位置;
  • exchangeLowHigh16()完成short型的高低位转换,int型的高低位转换使用exchangeLowHigh64()

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

dataInput=alloc2float(nt,ncdp); // 分配nt*ncdp(采样点数×道数)所需的内存空间,用来存放二维地震道数据
//其中,alloc2float是卸载alloc.h中的函数,创建一个float型的二维数组
//dataInput为二级指针,可简记为dataInput指向每一行的开头

memset(dataInput[0], 0, nt*ncdp * sizeof(float)); // 从第一行的开头开始,将内存块中nt*ncdp个字符赋值为0
// dataInput指向每行开头,而dataInput[0]则为整个二维数组的起始位置

// 在内存的动态存储区中分配ncdp个长度为sizetraceheader的连续空间
traceheaderArray = (segy*)calloc(ncdp,sizetraceheader);

temp = (int*)calloc(nt,sizeof(int));

//逐道读取道头与地震道数据
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个采样点的数据,进行IBM-->PC的转换,结果指向每一道开头(dataInput[itrace])
    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将temp位置后nt个采样点的数据,进行PC-->IBM的转换,结果指向每一道开头(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++)
 // 在每个循环末尾的"}"添加备注,便于寻找和区分

//在写操作完成后释放内存
free(temp); // free temp pointer
free(traceheaderArray); // free traceheader pointer
free2float(dataInput);  // free data input pointer
  • calloc(num,size):在内存的动态存储区中分配num个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL;
  • malloc(size):功能与calloc()相似,不同之处是malloc() 不会将内存值初始化为0,而 calloc()会将新申请的内存填充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 主函数main.cpp及运行结果

#include"ReadSeismic.h"

void main(){

	copySeismicDataIBM("Azi6-Ang35-BZ19-6-1.segy","Outputibm.segy");

}

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

以上就是C/C++实现segy文件的读取详解的详细内容,更多关于C++读取segy文件的资料请关注我们其它相关文章!

(0)

相关推荐

  • c++读取和写入TXT文件的整理方法

    如下所示: #include "stdafx.h" #include <iostream> //无论读写都要包含<fstream>头文件 #include <fstream> #include <iomanip> using namespace std; int main() { //ifstream从文件流向内存的ifstream表示文件输入流,意味着文件读操作 ifstream myfile("c://a.txt"

  • c++读取数据文件到数组的实例

    在刷题过程中,遇到的读取文件问题,只是记录自己的问题,新手~ 如果在一个txt文件当中有以下数据 1 2 3 4 5 6 7 8 9 10 1.如果我们只是简单将这些数据保存在一个数组中: #include <iostream> #include <fstream> using namespace std; int main() { int i,datalen=0; double num[100]; ifstream file("data.txt"); whil

  • C++读取配置文件的示例代码

    代码地址 https://github.com/gongluck/Code-snippet/tree/master/cpp/config 需求 开发中,读取配置文件信息必不可少.Windows平台有现成的API可用,也很方便.但是一旦项目迁移到Linux平台下,原先在Windows平台下的代码就全部作废.所以,实现一套跨平台的配置文件读取功能代码可以节省不少的劳动力. 实现 依赖于boost的ini_parser,可以实现跨平台读取ini格式的配置文件. // config.h /* * @Au

  • C++读取wav文件中的PCM数据

    前言 wav文件通常会使用PCM格式数据存储音频,这种格式的数据读取出来直接就可以播放,要在wav文件中读取数据,我们首先要获取头部信息,wav的文件结构里面分为多个chunk,我们要做的就是识别这些chunk的信息,获取音频的格式以及数据. 一.如何实现? 首先需要构造wav头部,wav文件音频信息全部保存在头部,我们要做的就是读取wav头部信息,并且记录PCM的相关参数. 1.定义头结构 只定义PCM格式的wav文件头,对于PCM格式的数据只需要下面3个结构体即可. struct WaveR

  • C++ txt 文件读取,并写入结构体中的操作

    如下所示: wang 18 001 li 19 002 zhao 20 003 代码如下: #include <string> #include <iostream> #include <fstream> using namespace std; struct people { string name; int age; string id; }p[20]; int main() { int n = 0; ifstream in( "a.txt" ,

  • C/C++实现segy文件的读取详解

    目录 1头文件ReadSeismic.h的编写及其规范 1.1程序描述.调用.声明.定义 1.2声明函数 1.3完整代码 2C++文件ReadSeismic.cpp的编写及其规范 2.1必要的说明 2.2定义读.写函数 2.3完整代码 3主函数main.cpp及运行结果 本文档将介绍SEGY的读取与写入过程,其中包括IBM与PC两种数据格式的转换. 程序将调用IEEE2IBM.cpp文件完成IBM与PC格式的互相转换. 新建头文件ReadSeismic.h与C++文件ReadSeismic.cp

  • Python学习之文件的读取详解

    目录 文件读取的模式 文件对象的读取方法 使用 read() 函数一次性读取文件全部内容 使用 readlines() 函数 读取文件内容 使用 readline() 函数 逐行读取文件内容 mode().name().closed() 函数演示 文件读取小实战 with open() 函数 利用with open() 函数读取文件的小实战 上一章节 我们学习了如何利用 open() 函数创建一个文件,以及如何在文件内写入内容:今天我们就来了解一下如何将文件中的内容读取出去来的方法. 文件读取的

  • Python学习之yaml文件的读取详解

    目录 yaml 文件的应用场景与格式介绍 yaml 文件的应用场景 yaml 文件的格式 第三方包 - pyyaml 读取 yaml 文件的方法 yaml文件读取演示案例 yaml 文件的应用场景与格式介绍 yaml 文件的应用场景 yaml其实也类似于 json.txt ,它们都属于一种文本格式.在我们的实际工作中, yaml 文件经常作为服务期配置文件来使用. 比如一些定义好的内容,并且不会修改的信息,我们就可以通过定义 yaml 文件,然后通过读取这样的文件,将数据导入到我们的服务中进行使

  • D3.js进阶系列之CSV表格文件的读取详解

    前言 之前在入门系列的教程中,我们常用 d3.json() 函数来读取 json 格式的文件.json 格式很强大,但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 OpenOffice Calc 等生成的表格文件,因为简单易懂,容易编辑. Microsoft Excel 通常会保存为 xls 格式, OpenOffice Calc 通常会保存为 ods 格式.这些格式作为表格文件来说都很强大,但要读取它们是有些麻烦的,D3 中也没有提供这样的方法.但是表格软

  • 对pandas写入读取h5文件的方法详解

    1.引言 通过参考相关博客对hdf5格式简要介绍. hdf5在存储的是支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的. 使用压缩可以提磁盘利用率,节省空间. 开启压缩也没有什么劣势,只会慢一点点. 压缩在小数据量的时候优势不明显,数据量大了才有优势. 同时发现hdf读取文件的时候只能是一次写,写的时候可以append,可以put,但是写完成了之后关闭文件,就不能再写了, 会覆盖. 另外,为什么单独说pandas,主要因为本人目前对于h5py这个包的理解不是很深入,不

  • python数据分析之文件读取详解

    目录 前言: 一·Numpy库中操作文件 二·Pandas库中操作文件 三·补充 总结 前言: 如果你使用的是Anaconda中的Jupyter,则不需要下载Pands和Numpy库:如果你使用的是pycharm或其他集成环境,则需要Pands和Numpy库 一·Numpy库中操作文件 1.操作csv文件 import numpy as np a=np.random.randint(0,10,size=(3,4)) np.savetext("score.csv",a,deliminte

  • Python3读取文件的操作详解

    目录 1.引言 2. fileinput 2.1 方法介绍 2.2 默认读取 2.3 处理一个文件 2.4 处理批量文件 2.5 读取与备份 2.5 重定向替换 2.6 进阶 3.总结 1.引言 小鱼:小屌丝, 这段代码为什么要开两个线程? 小屌丝:因为我要读写文件,还要备份文件,所以就开两个线程了. 小鱼:嗯,想法是对的,但是,还有一种简便的方法, 不需要开两个线程就能搞得定的. 小屌丝:额…难道是with open? 小鱼:不是. 小屌丝:那还有啥呢? 我咋想不起来了. 小鱼:嗯,这个方法很

  • Pandas实现在线文件和剪贴板数据读取详解

    目录 前言 read_html 在线文件1 在线文件2 读取在线CSV文件 Pandas读取剪贴板 前言 大家好,我是Peter~ 本文记录的是Pandas两种少用的读取文件方式: 读取在线文件的数据 读取剪贴板的数据 声明:本文案例和在线数据仅用于学术分享 read_html 该函数表示的是直接读取在线的html文件,一般是表格的形式:将HTML的表格转换为DataFrame的一种快速方便的方法. 这个方法对于快速合并来自不同网页上的表格非常有用,就省去了爬取数据再来读取的时间. 具体函数的参

  • .NetCore实现上传多文件的示例详解

    本章和大家分享的是.NetCore的MVC框架上传文件的示例,主要讲的内容有:form方式提交上传,ajax上传,ajax提交+上传进度效果,Task并行处理+ajax提交+上传进度,相信当你读完文章内容后能后好的收获,如果可以不妨点个赞:由于昨天电脑没电了,快要写完的内容没有保存,今天早上提前来公司从头开始重新,断电这情况的确让人很头痛啊,不过为了社区的分享环境,这也是值得的,不多说了来进入今天的正篇环节吧: form方式上传一组图片 先来看看咋们html的代码,这里先简单说下要上传文件必须要

  • Python中使用pypdf2合并、分割、加密pdf文件的代码详解

    朋友需要对一个pdf文件进行分割,在网上查了查发现这个pypdf2可以完成这些操作,所以就研究了下这个库,并做一些记录.首先pypdf2是python3版本的,在之前的2版本有一个对应pypdf库. 可以使用pip直接安装: pip install pypdf2 官方文档: pythonhosted.org/PyPDF2/ 里面主要有这几个类: PdfFileReader . 该类主要提供了对pdf文件的读操作,其构造方法为: PdfFileReader(stream, strict=True,

随机推荐