SEGY IO

推荐采用的IDE为Visual studio(VS),本文档将介绍SEGY文件的读取与写入过程,即SEGY文件的复制。

因此,新建头文件ReadSeismic.h与C++文件ReadSeismic.cpp,以及主函数main.cpp

1 SEGY简介

标准SEGY文件一般包括三部分:卷头、道头与地震道数据;

卷头(File Header) EBCDIC文件头(3200字节) 保存一些对地震数据体进行描述的信息
二进制文件头(400字节) 存储描述SEGY文件的数据格式、采样点数、采样间隔、测量单位等信息
道头(Trace Header) 240字节 存储某一地震道对应的线号、道号、采样点数、大地坐标等信息
地震道数据(Data) 若干采样点(1000、2000) 是对地震信号的波形按一定时间间隔Δt进行取样所得的一系列离散振幅值

SEGY文件由卷头及n个地震道记录组成:

SEGY样本示例:

图中横轴上730--->Line,1580、1582--->CDP,纵轴上1240、1260--->Time

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

2.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) 备注、改动信息等
**********************************************************************/

2.2 调用需要的C/C++头文件

//调用需要的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>

2.3 调用需要的非标准库头文件

注意使用双引号(" "),并将这些头文件添加到项目文件夹中。对于每个调用的非标准库,需要给出必要的注释说明。

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

2.4 定义全局变量及命名空间

对于代码中用到的物理量、常数等,使用#define定义常量并加以说明,避免函数中出现意义不明的常量。

#define PI 3.141592654   //Constant Number Definition
#define EPS 0.0000001 using namespace std;

2.5 声明函数

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

完整代码

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

 * 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" //(4)定义全局常量
#define PI 3.141592654 // Constant Number Definition
#define EPS 0.0000001 //(5)声明命名空间
using namespace std; //(6)声明函数名、输入、输出及其类型
bool copySeismicData(const char *filenameInput, const char *filenameOutput); //Copy seismic data from Inputfile to Outputfile

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

3.1 必要的说明

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

 Function:       copySeismicData                                                   (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)备注、改动信息等 *************************************************************************************************************/

3.2 定义读、写函数

#include "ReadSeismic.h"
bool copySeismicData(const char *filenameInput, const char *filenameOutput){ //实现代码
... }

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

bhedsegy均为定义在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

(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

fopen()的参数详解:

fopen(const char *filename, const char *mode)

  • filename -- 要打开的文件名称;
  • mode -- 文件访问模式;

(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 = 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); // 先写入卷头
  1. fread() 从给定流读取数据到指针所指向的数组中;

    fread(*ptr, size, nmemb,*stream)

    • ptr -- 指向带有最小尺寸 size*nmemb 字节的内存块的指针;
    • size -- 要读取的每个元素的大小,以字节为单位。
    • nmemb -- 元素的个数,每个元素的大小为 size 字节;
    • stream -- 指向 FILE 对象的指针。
  2. fwrite(*ptr, size, nmemb,*stream) 参数与fread()相同,把ptr所指向的数组中的数据写入到给定流stream中;

  3. _fseeki64的用法与fseek相同,表示从文件指定位置偏移一定字节数;前者具有更高的兼容性;

  4. _ftelli64ftell同理,返回给定流的当前文件位置;

    _fseeki64(*stream, offset, whence)

    • stream -- 指向 FILE 对象的指针;

    • offset -- 相对 whence 的偏移量,以字节为单位;

    • whence -- 表示开始添加偏移 offset 的位置。一般定义为SEEK_SET(文件开头)、SEEK_CUR(文件指针的当前位置)、SEEK_END(文件末尾)三类常量。

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

dataInput=(float*)calloc(nt,sizeof(float)); // 分配nt(采样点数)个元素所需的内存空间,用来存放单条地震道数据

for(int itrace= 0; itrace< ncdp; itrace++){

	fread(&traceheader, sizetraceheader,1, fpinput); // 指针fpinput自第一道道头开始移动,读取数据到traceheader中
fread(dataInput,nt*sizeof(float),1,fpinput); // 指针fpinput移动到道头末尾(数据开头),读入nt个采样点的数据到dataInput中 fwrite(&traceheader, sizetraceheader, 1, fpoutput);// 写入某一道头
fwrite(dataInput, nt * sizeof(float), 1, fpoutput);// 写入某一道地震数据 }//end for(int itrace= 0; itrace< ncdp; itrace++)
// 在每个循环末尾的"}"添加备注,便于寻找和区分 //分配内存calloc()与释放内存free()配合使用,在写操作完成后释放内存
free(dataInput); // free data input pointer
  1. calloc(num,size):在内存的动态存储区中分配num个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL
  2. malloc(size):功能与calloc() 相似,不同之处是malloc() 不会设置内存为零,而 calloc()会设置分配的内存为零。

完整代码

/*****************************************************************************
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 copySeismicData(const char *filenameInput, const char *filenameOutput){ bhed fileheader; // file header
segy traceheader; // trace 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 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;
_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);
fwrite(&fileheader, sizefileheader, 1, fpoutput); dataInput=(float*)calloc(nt,sizeof(float));
for(int itrace= 0; itrace< ncdp; itrace++){ fread(&traceheader, sizetraceheader,1, fpinput);
fread(dataInput,nt*sizeof(float),1,fpinput); fwrite(&traceheader, sizetraceheader, 1, fpoutput);
fwrite(dataInput, nt * sizeof(float), 1, fpoutput); }//end for(int itrace= 0; itrace< ncdp; itrace++) free(dataInput); // free data input pointer
fclose(fpinput); //close input file pointer
fclose(fpoutput); //close output file pointer return true; }

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

#include"ReadSeismic.h"

void main(){

	copySeismicData("Demo.segy","Output.segy");

}

运行主函数后,程序会读入OVT-BZ19-6-1_pc.segy,再写入到Output.segy,从而完成对Segy文件的复制。


附录

I SEGY文件卷头与道头中常用的属性

属性 变量名 位置/字节 备注
采样点 hns 卷头 此卷中每道的采样点数
格式 format 卷头
线号 fldr 道头/9-12 -
道号 cdp 道头/21-24 -
采样点数 nhs 道头/33-34 -
横坐标 sx 道头/73-76 -
纵坐标 sy 道头/77-80 -
采样点数 ns 道头/115-116 -
采样间隔 dt 道头/117-118 -
增益 gain 道头/119-120 1 = yes ; 2 = no

II 文件打开模式

模式 描述
"r" 以只读方式打开文件,该文件必须存在。
"r+" 以可读写方式打开文件,该文件必须存在。
"rb" 以只读方式打开一个二进制文件,只允许读数据。
"w" 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。
"w+" 创建一个用于读写的空文件。
"wb" 只写打开或新建一个二进制文件,只允许写数据。
"a" 追加到一个文件;写操作向文件末尾追加数据。如果文件不存在,则创建文件。
"a+" 打开一个用于读取和追加的文件。
"rw+" 读写打开一个文本文件,允许读和写。

C/C++语言读取SEGY文件笔记(一)的更多相关文章

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

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

  2. C/C++读取SEGY文件(三)

    SEGY IO (IBM&PC) 本文档将介绍SEGY的读取与写入过程,其中包括IBM与PC两种数据格式的转换. 程序将调用IEEE2IBM.cpp文件完成IBM与PC格式的互相转换. 新建头 ...

  3. R语言读取excel文件的3种方法

    R读取excel文件中数据的方法: 电脑有一个excel文件,原始的文件路径是:E:\R workshop\mydata\biom excel数据为5乘2阶矩阵,元素为                ...

  4. C语言读取PE文件信息(一)

    接下来的内容来源于对该博客文章http://www.pediy.com/kssd/pediy06/pediy7006.htm的解析. 一.打印Sections信息.下面的程序打印出Windows_Gr ...

  5. R语言读取EXCEL文件的各种方法

    路径问题 原始文件路径C:\Users\air\Desktop\1.txt R中有两种方法读取该路径 C:\\Users\\air\\Desktop\\1.txt C:/Users/air/Deskt ...

  6. R语言读取本地文件注意事项

    R里面应该用/,而不是\ ,或者用两个\\   R区分大小写,所以应该用C:,而不是c:

  7. c语言读取一个文件夹下的全部文件(jpg / png 文件)

    #include <cstdio> #include <cstring> #include <unistd.h> #include<dirent.h> ...

  8. C语言读取写入CSV文件 [一]基础篇

    本系列文章目录 [一] 基础篇 [二] 进阶篇--写入CSV [三] 进阶篇--读取CSV 什么是CSV? CSV 是一种以纯文本形式存储的表格数据,具体介绍如下(来自维基百科): 逗号分隔值(Com ...

  9. R语言笔记004——R批量读取txt文件

    R批量读取txt文件 本文数据,代码都是参考的是大音如霜公众号,只是自己跟着做了一遍. path<-'C:\\Users\\Administrator\\Desktop\\docs' docs& ...

随机推荐

  1. bom-offset

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. linux计划任务之cron

    目录 cron计划任务之用户级 cron计划任务之系统级 cron计划任务之用户级 1.安装crond centos7 执行命令: # yum install -y crontabs /bin/sys ...

  3. Cell的重用原理

    iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存.要解决该问题,需要重用UITableViewC ...

  4. 微服务技术栈简单介绍,Eureka和Ribbon的引入和使用

    一.了解微服务架构 1.微服务技术栈 整体框架 整体学习规划路线2.微服务与单体架构的区别 单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署 优势 结构简单 部署成本低 缺点 耦合度高, ...

  5. JIRA 测试循环的创建和使用

    3.测试循环 3.1测试循环的创建      测试人员编写完测试用例,并评审通过后:测试负责人可以计划测试循环. 点击JIRA 选择列表栏中的"测试".点击"计划循环测试 ...

  6. 流量录制与回放在vivo的落地实践

    一.为什么要使用流量录制与回放? 1.1 vivo业务状况 近几年,vivo互联网领域处于高速发展状态,同时由于vivo手机出货量一直在国内名列前茅,经过多年积累,用户规模非常庞大.因此,vivo手机 ...

  7. opencv笔记--ORB

    ORB detector 使用 FAST detector 和 BRIEF descriptor 基本思路.在介绍 ORB 之前,首先对 FAST 与 BRIEF 进行说明. 1 FAST FAST( ...

  8. 搭建 NFS 服务 & 实时同步

    今日内容 NFS简介 实现 NFS 文件同步功能 NFS 配置详解 统一用户 搭建 web 服务 NFS 实现文件共享 内容详细 1.NFS 简介 1.1 介绍 实现多台 web 服务器可以共享数据资 ...

  9. 四探循环依赖 → 当循环依赖遇上 BeanPostProcessor,爱情可能就产生了!

    开心一刻 那天知道她结婚了,我整整一个晚上没睡觉,开了三百公里的车来到她家楼下,缓缓的抽了一支烟...... 天渐渐凉了,响起了鞭炮声,迎亲车队到了,那天披着婚纱的她很美,真的很美! 我跟着迎亲车队开 ...

  10. 聊聊几个阿里 P8、P9 程序员的故事

    大家好,我是对白. 阿里 P8 程序员年薪百万已经是公开的秘密了,有人关心他们年薪百万,而我更加关注阿里这些 P8.P9 程序员的成长故事,在聊这些大牛的故事之前,跟大家稍微简单聊下阿里技术人等级制度 ...