由于项目需要,需要对二进制文件进行读写、转换。

  文件说明:由其他程序得到的二进制文件,文件内容为:包含23543个三角形、13270个顶点的三角网所对应的721组流速矢量(u、v)文件,通俗些说,一条数据包含两个双精度型的数值,每组数组包含23543条数据,如果以一个双精度数值为单位,则总共有23543 * 721 * 2 =33,949,006条数据。由Fortran程序以每 8 Byte存储一个数值的二进制文件存储,最终文件大小为下图所示:

              

  

  测试:从该文件读出数据之后,转换为十进制,存储到另一个文件中。

  

/**
* 针对大文件存储,请依次调用beginSave、AddSave、endSave。
*
* @author CK
*
*/
public class DataUtil { DataOutputStream BinaryOut=null;
BufferedWriter TextOut=null;
String FilePath=null;
enum SaveFileType{Text,Binary};
SaveFileType SaveFileType; /**
* double转byte[]
*
* @param d
* @return
*/
public static byte[] double2Bytes(double d) {
long value = Double.doubleToRawLongBits(d);
byte[] byteRet = new byte[8];
for (int i = 0; i < 8; i++) {
byteRet[i] = (byte) ((value >> 8 * i) & 0xff);
}
return byteRet;
} /**
* byte[]转double
*
* @param arr
* @return
*/
public static double bytes2Double(byte[] arr) {
long value = 0;
for (int i = 0; i < 8; i++) {
value |= ((long) (arr[i] & 0xff)) << (8 * i);
}
return Double.longBitsToDouble(value);
}
/**
* 大型数据存储之开始存储
* @param FilePath 文件路径
* @param saveFileType 保存的文件类型,文本文件、双精度所存的二进制文件
* @return
* @throws IOException
*/
public boolean BeginSave(String FilePath,SaveFileType saveFileType) throws IOException {
if (FilePath == "" || FilePath == null) {
System.out.println("the SavePath is null.");
return false;
}
this.FilePath=FilePath;
this.SaveFileType=saveFileType;
File dataFile = new File(FilePath);
if (!dataFile.getParentFile().exists()) {
dataFile.getParentFile().mkdirs();
}
if (dataFile.exists()) {
dataFile.delete();
}
dataFile.createNewFile();
switch(this.SaveFileType){
case Text:
TextOut= new BufferedWriter(new FileWriter(dataFile,true));
break;
case Binary:
BinaryOut = new DataOutputStream(new FileOutputStream(dataFile,true));
break;
default:
break; }
return true;
}
/**
* 大型文件存储之追加存储
* @param DataStr 若是文本存储则无要求,若是双精度的二进制文件,以若干空格隔开
* @return
* @throws IOException
*/
public boolean AddSave(String DataStr) throws IOException{
switch(this.SaveFileType){
case Text:
this.TextOut.append(DataStr);
break;
case Binary:
DataStr=DataStr.trim();
String[] dataArray=DataStr.split("\\s+");
for(int i=0;i<dataArray.length;i++){
this.BinaryOut.write(double2Bytes(Double.parseDouble(dataArray[i])));
}
break;
default:
break; } return true;
}
/**
* 大型文件存储之结束保存,清空缓存、关闭文件。
* @return
* @throws IOException
*/
public boolean EndSave() throws IOException{
switch(this.SaveFileType){
case Text:
this.TextOut.flush();
this.TextOut.close();
break;
case Binary:
this.BinaryOut.flush();
this.BinaryOut.close();
break;
default:
break;
} return true;
}
/**
* 将字符串保存为文本文件(一次完成)
*
* @param DataStr
* 文件内容
* @param SavePath
* 文件路径,包含文件名、后缀
* @return
* @throws IOException
*/
public boolean saveTextFile(String DataStr, String SavePath)
throws IOException {
if (DataStr == "" || DataStr == null) {
System.out.println("the dataStr is null.");
return false;
}
if (SavePath == "" || SavePath == null) {
System.out.println("the SavePath is null.");
return false;
}
File dataFile = new File(SavePath);
if (!dataFile.getParentFile().exists()) {
dataFile.getParentFile().mkdirs();
}
if (dataFile.exists()) {
dataFile.delete();
}
dataFile.createNewFile();
BufferedWriter out; out = new BufferedWriter(new FileWriter(dataFile)); out.append(DataStr);
out.flush();
out.close(); return true;
} /**
* 双精度存为二进制数据(一次存储)
*
* @param DataStr 双精度数据组成的字符串,以若干空格隔开
* @param OutputPath
* @return
* @throws IOException
*/
public boolean saveBinaryFile(String DataStr, String OutputPath) throws IOException { if (DataStr == "" || DataStr == null) {
System.out.println("the dataStr is null.");
return false;
}
if (OutputPath == "" || OutputPath == null) {
System.out.println("the OutputPath is null.");
return false;
}
File dataFile = new File(OutputPath); if (!dataFile.getParentFile().exists()) {
dataFile.getParentFile().mkdirs();
}
if (dataFile.exists()) {
dataFile.delete();
}
dataFile.createNewFile();
DataOutputStream out;
out = new DataOutputStream(new FileOutputStream(dataFile));
// 数据处理
DataStr=DataStr.trim();
String[] dataArray=DataStr.split("\\s+");
for(int i=0;i<dataArray.length;i++){
out.write(double2Bytes(Double.parseDouble(dataArray[i])));
}
out.flush();
out.close();
return true; }
}

  代码说明:其中byte[]与double互转为在互联网上查到的方法,具体是哪位大神的我忘记了,在这里为了记录就贴出来啦,上述代码包含了处理小型文件时,将所有内容存在缓存中,之后再一次性写入文本文件、二进制文件中的方法,还包含了对较大型文件的读写方法,下面是自己的一个读写测试。

/**
* 测试二进制大文件读写(200M左右)
* @author ck
*
*/
public class FileTest {
static String inputFilePath=""; //输入文件路径,包含文件名后缀
static String outputFilePath=""; //输出文件名,包含文件名后缀 public static void file2file() throws IOException{
DataUtil dataUtil=new DataUtil();
DataInputStream br=new DataInputStream(
new BufferedInputStream(
new FileInputStream(inputFilePath)));
dataUtil.BeginSave(outputFilePath, SaveFileType.Text); //初始化,创建文件,采用文件追加存储的思路
byte[] oneData=new byte[8];
int i=0,count =0 ;
while(br.read(oneData, 0, 8)!=-1){
i=i+1;
dataUtil.AddSave(String.valueOf(DataUtil.bytes2Double(oneData)));
if(i/23543==0){
count++;
System.out.println(count+"\n"); }
}
dataUtil.EndSave(); //将还在缓存中的数据写入到文件中,关闭文件。
}
}

此次测试代码很快就run完了,但是输出文件的生成大概用了近半分钟(刻意秒表计时了一次),尝试用一次性读写的办法,卡很久,也没有出结果。所得的十进制文本文件,大小为这么多:

  我想,原来Fortran程序作者的初衷应该是觉得二进制存储比十进制节省空间吧,事实上也确实节省了一半多的空间。

  恩,此次记录完毕。

Java———较大二进制文件的读、写的更多相关文章

  1. Java IO RandomAccessFile 任意位置读/写

    随机读写类 RandomAccessFile的唯一父类是Object,与其他流父类不同.是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必 ...

  2. 1月中旬值得一读的10本技术新书(机器学习、Java、大数据等)!

    1月中旬,阿里云云栖社区 联合 博文视点 为大家带来十本技术书籍(机器学习.Java.大数据等).以下为书籍详情,文末还有福利哦! 书籍名称:Oracle数据库问题解决方案和故障排除手册 内容简介 & ...

  3. java读/写文件

    读取文件参考:https://blog.csdn.net/weixin_42129373/article/details/82154471 写入文件参考:https://blog.csdn.net/B ...

  4. java filechannel大文件的读写

    java读取大文件 超大文件的几种方法 转自:http://wgslucky.blog.163.com/blog/static/97562532201332324639689/   java 读取一个 ...

  5. 【原创】用JAVA实现大文件上传及显示进度信息

    用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 (本文提供全部源码下载,请访问 https://github.com/grayprince/UploadBigFil ...

  6. java处理大文本方案

    转载自:http://langgufu.iteye.com/blog/2107023 java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类, ...

  7. 用JAVA实现大文件上传及显示进度信息

    一. 大文件上传基础描述: 各种WEB框架中,对于浏览器上传文件的请求,都有自己的处理对象负责对Http MultiPart协议内容进行解析,并供开发人员调用请求的表单内容. 比如: Spring 框 ...

  8. java mysql大数据量批量插入与流式读取分析

    总结下这周帮助客户解决报表生成操作的mysql 驱动的使用上的一些问题,与解决方案.由于生成报表逻辑要从数据库读取大量数据并在内存中加工处理后在 生成大量的汇总数据然后写入到数据库.基本流程是 读取- ...

  9. java之大文件分段上传、断点续传

    文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用 ...

随机推荐

  1. STL之关联容器的映射底层

    STL的关联容器有set, map, multiset, multimap.用于实现它们的底层容器有划入标准的rb_tree和待增加标准的hashtable. 底层容器rb_tree为上层容器提供了一 ...

  2. DMA32映射问题

    近期在调试PCIe的行情加速卡的驱动.当中使用DMA在CPU和FPGA间数据传输. 最開始使用的是低16M的DMA ZONE的内存,用slab分配器的kmalloc分配获取.但因为最新的需求,须要使用 ...

  3. 一个有趣的问题:ls -l显示的内容中total究竟是什么?

    当我们在使用ls -l的命令时,我们会看到例如以下类似的信息. 非常多人可能对于第一行的total 12的数值并非非常在意,可是你是否想过,它到底是什么意思? man中的说明,我们能够看出total的 ...

  4. 怎样在gluster的源代码中加入自己的xlator

    本文并不说明怎样编写一个xlator.在glusterfs3.6.1下验证成功 目标在glusterfs-3.6.1/xlators/debug/下建立一个自己的xlator库并能够统一安装到系统文件 ...

  5. Python按行输出文件内容具体解释及延伸

    下面两端測试代码分别为笔者所写,第一段为错误版本号.后者为正确版本号: #! /usr/bin/python2.7 try:     filename = raw_input('please inpu ...

  6. javascript里的prototype

    在javascript中,prototype是函数的一个固有属性,其他对象,比如字符串什么的,并没有这个属性. 这个属性做什么用呢? 1.用于该函数的所有实例进行共享 比如,共同的属性,共同的方法.类 ...

  7. c# Custom Controls

    http://www.cnblogs.com/light169/archive/2008/06/11/1217139.html

  8. c# Http下载

    1.首先是服务器上发布资源,如果资源时自定义格式,比如 .zidingyi结尾的后缀文件,需要在MIME类型上添加处理方式 需要注意的是.net里面要设置 System.Net.ServicePoin ...

  9. [测试]单元测试框架NUnit

    说到测试,相信大家都或多或少了解. 按照各自分类,就自己知道包括 A.单元测试.集成测试.系统测试 B.白盒测试.黑盒测试 C.压力测试.性能测试.安全测试 ...... 反正是太多太多.就做开发以来 ...

  10. 21 WPF数据视图

    视图对象 当你绑定集合到ItemsControl,在幕后数据视图被安静地创造.视图位于数据源和绑定控件之间.数据视图是通往数据源的一个窗口.它跟踪当前项目,它支持诸如排序,过滤,和分组特征.这些特征独 ...