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. Nodejs ORM框架Sequelize快速入门

    Nodejs ORM框架Sequelize快速入门 什么是ORM? 简单的讲就是对SQL查询语句的封装,让我们可以用OOP的方式操作数据库,优雅的生成安全.可维护的SQL代码.直观上,是一种Model ...

  2. Centos8安装virtualbox

    一.执行以下命令并启用 VirtualBox 和 EPEL 包仓库 dnf config-manager --add-repo=https://download.virtualbox.org/virt ...

  3. async同步异步

    1.同步:var async = require("async"); async.series([step1, step2, step3],function(err, values ...

  4. 帆软报表(finereport)使用Event 事件对象 (target)修改提示框样式

    target 事件属性 Event 对象 定义和用法 target 事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素.文档或窗口. 语法 event.target 定义结束事件Jav ...

  5. 字符编码和Python代码操作文件

    字符编码和Python代码操作文件 读写模式之a模式 # a模式 只追加模式 # 路径不存在:自动创建 with open(r'a.txt','a',encoding='utf8') as f: pa ...

  6. Solution -「51nod 1868」彩色树

    \(\mathcal{Description}\)   Link & 双倍经验 Link.   给定一棵 \(n\) 个结点的树,每个结点有一种颜色.记 \(g(u,v)\) 表示 \(u\) ...

  7. 『无为则无心』Python基础 — 44、对文件和文件夹的操作

    目录 1.os模块介绍 2.查看os模块相关文档 3.os模块常用方法 (1)文件重命名 (2)删除文件 (3)创建文件夹 (4)删除文件夹 (5)获取当前目录 (6)改变默认目录 (7)获取目录列表 ...

  8. Linux-CPU优化之平均负载率

    一.平均负载率定义 平均负载是指单位时间内,系统处于可运行状态 和不可中断状态 的平均进程数,也就是平均活跃进程数,它和CPU 使用率并没有直接关系. 可运行状态的进程:是指正在使用 CPU 或者正在 ...

  9. Java IO模型:BIO、NIO、AIO

    Java IO模型:BIO.NIO.AIO 本来是打算直接学习网络框架Netty的,但是先补充了一下自己对Java 几种IO模型的学习和理解.分别是 BIO.NIO.AIO三种IO模型. IO模型的基 ...

  10. 云原生 PostgreSQL - CrunchyData PGO 教程:创建、连接、删除 Postgres 集群

    入门 作为安装的一部分,请确保您已完成以下操作: 分叉 Postgres Operator 示例存储库并将其克隆到您的主机. https://github.com/CrunchyData/postgr ...