NetBeans 8.2 开发 CIFLog3.5 - 数据导入导出案例
NetBeans 8.2 开发 CIFLog3.5 - 数据导入导出案例
- NetBeans 8.2 开发 CIFLog3.5 - 数据导入导出案例
- NetBeans 8.2 开发 CIFLog3.5 - 数据导入导出案例
- 开发数据导入导出模块
- (1)新建模块
- (2)添加模块依赖关系
- (3)新建Java类
- (4)介绍数据导入流程
- (5)编写入口类代码
- (6)编写导入功能代码
- (7)完成导入功能
- (8)数据导出功能实现与完成
CIFLog测井平台由中国石油勘探开发研究院李宁团队研发,是国内行业领先的测井软件,其功能强大,在教学和科研中被广泛使用。目前版本:3.5(博主已知是这个),石油科研院所和高校可申请免费使用。
NetBeans 8.2 开发 CIFLog3.5 - 数据导入导出案例
参考书籍《CIFLog测井软件平台用户应用系统开发》
NetBeans 8.2 开发 CIFLog3.5 - 数据导入导出案例
本博客内容上接 NetBeans 8.2 开发 CIFLog3.5 - 数据访问案例
没有安装CIFLog的小伙伴可以参考 NetBeans 8.2 开发 CIFLog3.5 - 创建WelcomeDemo
开发数据导入导出模块
(1)新建模块
首先打开netbeans 8.2
新建模块
选择 NetBeans 模块,然后选择 NetBeans 模块
给项目命名,DataImportDemo
设置代码名称基
cif.demo.dataimport
点击 完成 ,成功创建模块
(2)添加模块依赖关系
对 模块 右键,选择 属性
点击左边的 库 ,然后点 添加依赖
添加如下的依赖
(3)新建Java类
进入 源包,对刚才创建的包右键,选择Java类
类名为 Text1DConversion
继承 ConversionBase 类
对 类名 按住 alt+回车,点击实现全部抽象方法
(4)介绍数据导入流程
以导入 .txt 文本文件为例子
打开CIFlog选择数据后,会展示出如下界面,点击红色的图案,进入数据格式转换界面
左下角部分会展示出许多数据格式转换的模块,这些都是已经提供好的,可以拿来直接用
点击导入数据按钮,可以选择一个数据导入,然后点击转换,根据已有的模块,可以把数据转换成我们需要的类型的数据
左下角的这些模块都已jar的方式放到指定的目录下,这样CIFLog会自动识别并导入模块,格式转换模块的路径在安装目录下的 conversionJars 文件夹中
在实现我们自己的数据转换模块后,把jar文件放到这个路径下,就可以使用了,接下来就开始编写代码
(5)编写入口类代码
首先编写入口类,右键 源包,点击新建 Java 包
创建名为 conversion 的包
对 conversion 包右键,创建 Java类
创建名为 ConversionEntry 的Java类
需要实现 ConversionEntryInterface 接口,并重写其中的方法
public class ConversionEntry implements ConversionEntryInterface {
@Override
public ConversionBase getConversionInstance() {
return new Text1DConversion();
}
}
(6)编写导入功能代码
接下来编写 Text1DConversion 类中的代码
这里有一个代码编写顺序,不按顺序会出现问题。
- 实现getFormatTypeString方法
- 实现getFormatExtension方法
- 实现isThisFormat方法
- 实现**fileScan()**方法
首先,当我们点击这个图标后,CIFLog会自动识别conversionJars文件夹下的jar包,根据左括号后面的字符串字母顺序进行排序,因此可以看到A开头的模块在前,Z开头的在最后
这个左下角展示的文字,由getFormatTypeString方法的返回值来设置
所以,我们首先要实现这个方法
否则在点击图标的时候会报错
根据详细信息的错误提示,可以看到是这个方法内部报错了
所以第一步要实现这个方法
但是
,实现这个方法有规则,必须包含 ( ,左括号
如果不包含,按照如下写法,就会报错误
如果打开界面时,出现的下面这个错误,这个错误是因为没有写入口类导致的,需要写 ConversionEntry 类
那么数组越界错误是怎么回事,为什么会出现呢?
我们查看详细情况,看到里面有个compare方法,接下来就要去这个方法,看看源码是怎么实现的
进入 ConversionPanel 类,找到 compare 方法
可以看到这里有具体的实现代码,不过不是Java的字节码,下面逐一解析
- aload_1; 加载本地变量 1(ConversionBase 对象)
- invokevirtual cif/formatconversion/ConversionBase.getFormatTypeString:()Ljava/lang/String; 对象调用obj1.getFormatTypeString()
- ldc “\(”; 加载常量字符串 “\(”
- invokevirtual java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String; 使用 split(“\(”) 方法拆分字符串,以 ( 左括号进行分割,返回一个 String 数组。
- iconst_1 加载常数 1
- aaload 取数组索引 1 处的字符串,即取 split(“\(”) 结果的第 2 个元素
- aload_2 加载本地变量 2(另一个 ConversionBase 对象)
- invokevirtual cif/formatconversion/ConversionBase.getFormatTypeString:()Ljava/lang/String; 对象调用obj2.getFormatTypeString()
- ldc “\(” 加载常量字符串 “\(”
- invokevirtual java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String; 使用 split(“\(”) 方法拆分字符串
- iconst_1 加载常数 1
- aaload 取数组索引 1 处的字符串,即取 split(“\(”) 结果的第 2 个元素
- invokevirtual java/lang/String.compareTo:(Ljava/lang/String;)I 调用 compareTo() 比较两个字符串
- ireturn 返回 compareTo() 的结果
最后返回的是左括号右边字符串的比较结果,因此最后以左括号右边的字符串进行排序,可以看到下图名称的排序顺序,以左括号右边的字符串排序的
由于字节码中出现了这段代码
iconst_1 加载常数 1
aaload 取数组索引 1 处的字符串,即取 split(“\(”) 结果的第 2 个元素
也就是说如果不包含左括号,字符串分割的结果中,就不会出现第二个元素,如果此时访问索引为1处的元素,就会抛出ArrayIndexOutOfBoundsException的异常
因此我们要修改代码,修改为带有左括号的
@Override
public String getFormatTypeString() {
return "Test1DConversion(Test)";
}
接下来实现getFormatExtension方法,书上介绍:该方法获得数据格式后缀字符串,如果是该格式支持多个字符串后缀,使用“,”分割
我们这里处理 .txt 文本文件,所以我们直接返回"txt"就可以了
如果不实现,就会出现下面的问题,CIFLog不知道你要处理哪种格式的数据,因此左下角不会出现我们编写的模块
接下来,第三步,实现isThisFormat方法
public boolean isThisFormat(String string) throws Exception {
String extension = ConversionPathUtil.getExtension(string);
return extension.compareToIgnoreCase("TXT") == 0;
}
该方法的作用是判断导入的文件是否具有 .txt 后缀(不区分大小写)。如果是 .txt 文件,方法返回 true;否则返回 false。
如果不实现这个方法,当你选择了一个 .txt 文件后,右边会出现the specified file is an unrecognized format.
接下来,第四步,实现 fileScan() 方法
public StringBuffer fileScan() {
StringBuffer strBuffer = new StringBuffer("123");
String s; // Read the string formed by each line of content in the file.
int dataRowNum = 0;
try {
BufferedReader in = new BufferedReader(
new FileReader(new File(this.selectedFilePath)));
while ((s = in.readLine()) != null){
if (dataRowNum == 0) {
this.wellName = s.split("=")[1];
} else if (dataRowNum == 1) {
this.curDepth = this.startDepth = Double.parseDouble(s.split("=")[1].trim());
} else if (dataRowNum == 2) {
this.endDepth = Double.parseDouble(s.split("=")[1].trim());
} else if (dataRowNum == 3) {
this.depthLev = Double.parseDouble(s.split("=")[1].trim());
} else if (dataRowNum == 4) {
this.curveNames = Optional.of(s.replaceFirst("CURNAMES", ""))
.map(str -> str.split(","))
.map(Arrays::stream)
.map(stream -> stream.map(String::trim))
.map(stream -> stream.toArray(String[]::new))
.orElse(new String[]{});
}
if (dataRowNum >= this.MAX_DISPLAY_ROW) {
strBuffer.append("There is a lot of displayed text. Currently, only the first ")
.append(this.MAX_DISPLAY_ROW).append(" lines are shown.");
break;
}
strBuffer.append(s).append("\n");
dataRowNum++;
}
} catch (IOException ex) {
Logger.getLogger(Text1DConversion.class.getName()).log(Level.SEVERE, null, ex);
}
return strBuffer;
}
这段代码用到了Java 8的新特性,但是默认的情况下,netbeans使用的Java 7的语法,因此会爆红
对 模块 点击右键,选择 属性
左边寻找 源 ,把其修改为 1.8
这样就不会爆红了,如果你不想使用这种方式,可以替换为如下代码
String curveNamesString = s.replaceFirst("CURNAMES", ""); // 去掉 "CURNAMES" 前缀
String[] curveNamesArray = curveNamesString.split(","); // 使用逗号分割字符串
for (int i = 0; i < curveNamesArray.length; i++) {
curveNamesArray[i] = curveNamesArray[i].trim(); // 去除每个名字两端的空格
}
this.curveNames = curveNamesArray; // 将处理后的数组赋值给成员变量
这个方法的作用就是读取导入的文件的内容,最后展示出来
到这里,就实现了数据的导入功能了,接下来测试
点击上方的 清理和构建项目
进入当前项目的目录下,找到下面路径下的 .jar
E:\CIFLog-Tutorial\build\cluster\modules
注意,模块里也有build文件夹,我们要进入的是套件里的build,不是模块的
把产生的 cif-demo-dataimport.jar 放到 D:\CIFLog3x64\conversionJars目录下
(7)完成导入功能
启动CIFLog软件,这里并不是运行绿色的三角,打开数据转换,导入数据,可以看到成功显示出来了,数据如下
ELLNAME=testwell
STDEP=5860.000000
ENDEP=6546.000000
LEVEL=0.125000
CURNAMES AC,CAL,DEN,GR
#DEPTH AC CAL DEN GR
5860.000000 -9999.00000 5.86100 -9999.00000 37.03200
5860.125000 -9999.00000 5.84400 -9999.00000 36.18300
5860.250000 -9999.00000 5.86100 5860.250000 37.11200
(8)数据导出功能实现与完成
在 \conversionJars 文件夹里(博主为了测试自己写的模块,把原来的模块放到了一个文件夹里,original文件夹),有已经实现的案例,如果要实现数据导出功能,按照书上的代码是实现不了的,这里给大家说一下,如何查看已经实现好的功能代码
双击这个jar,例如双击Text1DFormatConversion.jar
点击左边的conversion,可以看到里面有已经实现的字节码文件,点击去看一个,了解Java的小伙伴是可以看懂的
例如我用idea打开Text1DConversion.class文件,如下图
对于数据导出功能,博主这里就不实现了,大家参考已经提供的模块,自行实现一下。
我们打开CIFLog,是可以直接使用已经提供的模块的。