C/C++语言读取SEGY文件笔记(一)
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)定义待使用的结构体变量、数值型变量
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
(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); // 先写入卷头
fread()
从给定流读取数据到指针所指向的数组中;fread(*ptr, size, nmemb,*stream)
- ptr -- 指向带有最小尺寸 size*nmemb 字节的内存块的指针;
- size -- 要读取的每个元素的大小,以字节为单位。
- nmemb -- 元素的个数,每个元素的大小为 size 字节;
- stream -- 指向 FILE 对象的指针。
fwrite(*ptr, size, nmemb,*stream)
参数与fread()
相同,把ptr
所指向的数组中的数据写入到给定流stream
中;_fseeki64
的用法与fseek
相同,表示从文件指定位置偏移一定字节数;前者具有更高的兼容性;_ftelli64
与ftell
同理,返回给定流的当前文件位置;_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
calloc(num,size)
:在内存的动态存储区中分配num
个长度为size
的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL
;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文件笔记(一)的更多相关文章
- C/C++语言读取SEGY文件(二)
SEGY IO (2D) 本文档将介绍SEGY的读取与写入过程,即SEGY文件的复制,并且在实现过程采用采样点×道数二维数组的形式读写. 新建头文件SegyDataIO2D.h与C++文件SegyDa ...
- C/C++读取SEGY文件(三)
SEGY IO (IBM&PC) 本文档将介绍SEGY的读取与写入过程,其中包括IBM与PC两种数据格式的转换. 程序将调用IEEE2IBM.cpp文件完成IBM与PC格式的互相转换. 新建头 ...
- R语言读取excel文件的3种方法
R读取excel文件中数据的方法: 电脑有一个excel文件,原始的文件路径是:E:\R workshop\mydata\biom excel数据为5乘2阶矩阵,元素为 ...
- C语言读取PE文件信息(一)
接下来的内容来源于对该博客文章http://www.pediy.com/kssd/pediy06/pediy7006.htm的解析. 一.打印Sections信息.下面的程序打印出Windows_Gr ...
- R语言读取EXCEL文件的各种方法
路径问题 原始文件路径C:\Users\air\Desktop\1.txt R中有两种方法读取该路径 C:\\Users\\air\\Desktop\\1.txt C:/Users/air/Deskt ...
- R语言读取本地文件注意事项
R里面应该用/,而不是\ ,或者用两个\\ R区分大小写,所以应该用C:,而不是c:
- c语言读取一个文件夹下的全部文件(jpg / png 文件)
#include <cstdio> #include <cstring> #include <unistd.h> #include<dirent.h> ...
- C语言读取写入CSV文件 [一]基础篇
本系列文章目录 [一] 基础篇 [二] 进阶篇--写入CSV [三] 进阶篇--读取CSV 什么是CSV? CSV 是一种以纯文本形式存储的表格数据,具体介绍如下(来自维基百科): 逗号分隔值(Com ...
- R语言笔记004——R批量读取txt文件
R批量读取txt文件 本文数据,代码都是参考的是大音如霜公众号,只是自己跟着做了一遍. path<-'C:\\Users\\Administrator\\Desktop\\docs' docs& ...
随机推荐
- 基于Apache的Tomcat负载均衡和集群(2)
反向代理负载均衡 (Apache+JK+Tomcat) 使用代理服务器可以将请求转发给内部的Web服务器,让代理服务器将请求均匀地转发给多台内部Web服务器之一上,从而达到负载均衡的目的.这种代理方式 ...
- Git忽略文件.gitignore的使用
本博客旨在自我学习使用,如有任何疑问请及时联系博主 1.WHY? 当你使用git add .的时候有没有遇到把你不想提交的文件也添加到了缓存中去?比如项目的本地配置信息,如果你上传到Git中去其他人p ...
- 一招教你IDEA中Java程序如何打包,以及打包后如何运行
前言 编写程序 程序打包 测试运行 IDEA作为目前按最主流的Java程序项目编写工具,越来越受到开发人员的青睐.idea因为其五花八门的功能,让你在开发过程中效率显著提高.那么对于初学者来说,如何通 ...
- nginx中的模块分类及常见核心模块有哪些
1.模块分类 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 .配置文件解析 .事件驱动机制 .进程管理等核心功能 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如 ...
- MybatisPlus二级缓存
一.序言 本文承接[Mybatis缓存体系探究],提供基于MybatisPlus技术可用于生产环境下的二级缓存解决方案. 1.前置条件 掌握MyBatis二级缓存的原理 有关MyBatis缓存原理内容 ...
- Java一维与二维数组的拷贝与排序
Java一维与二维数组的拷贝与排序 目录 Java一维与二维数组的拷贝与排序 Arrays.sort() 一维数组升序排序 二维数组按行升序排序 二维数组按列升序排序 Java中的数组 Java中数组 ...
- 《PHP程序员面试笔试宝典》——如何应对自己不会回答的问题?
如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 在面试的过程中,对面试官提出的问题求职者并不是都能回答出来,计算机技术博大精深,很少有人能对计算机技术的各个分支学科了如 ...
- aspnetcore 使用serilog日志
而在实际项目开发中,使用第三方日志框架来记录日志也是非常多的,首先一般基础的内置日志记录器在第三方日志框架中都有实现,然后很多第三方日志框架在功能上更强大和丰富,能满足我们更多的项目分析和诊断的需求. ...
- CentOS7 下 ldap 部署
环境准备 # 关闭防火墙以及selinux,生产环境中,以实际需求为准 [root@localhost ~]# hostnamectl --static set-hostname ldap-serve ...
- .NET 云原生架构师训练营(权限系统 代码重构)--学习笔记
目录 模块拆分 代码重构 模块拆分 代码重构 AuthenticationController PermissionController IAuthorizationMiddlewareResultH ...