深刻的体会就是,“java.lang.NullPointer.Exception”就是空指针异常可能是由于数组部分元素未被初始化引起的。

1)使用jmatio将mat数据转化为SequenceFile形式的数据,代码如下:

 /**
* Created with IntelliJ IDEA.
* User: hadoop
* Date: 16-3-6
* Time: 上午10:56
* To change this template use File | Settings | File Templates.
*/
import com.jmatio.io.MatFileReader;
import com.jmatio.types.*;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import java.net.URI;
import org.apache.hadoop.mapreduce.*;
public class mat2Seq {
public static void main(String[] args) throws IOException {
writeMat2Seq("data/100_100/F100.mat","SeqOutput/F");
writeMat2Seq("data/100_100/b100.mat","SeqOutput/b");
writeMat2Seq("data/100_100/d100.mat","SeqOutput/d");
writeMat2Seq("data/100_100/s100.mat","SeqOutput/s");
writeMat2Seq("data/100_100/u100.mat","SeqOutput/u");
} public static void writeMat2Seq(String matPath,String SeqOutput) throws IOException {
MatFileReader reader=new MatFileReader(matPath);
MLArray mlArray=reader.getMLArray("a");
MLDouble doubleValue=(MLDouble)mlArray;
double[][] matrix=doubleValue.getArray();
Configuration conf =new Configuration();
FileSystem fs=FileSystem.get(URI.create(SeqOutput),conf);
IntWritable key=new IntWritable();
DoubleArrayWritable value=new DoubleArrayWritable();
SequenceFile.Writer writer=null;
try {
writer=SequenceFile.createWriter(fs,conf,new Path(SeqOutput),key.getClass(),
value.getClass());
if (matPath.endsWith("F100.mat")){ //左矩阵F依次将行存储到Seq
DoubleWritable[] rowVector=new DoubleWritable[matrix.length];
for (int i=0;i<matrix.length;++i){
for (int j=0;j<matrix[0].length;++j){
rowVector[j]=new DoubleWritable(0);
rowVector[j].set(matrix[i][j]);
}
value.set(rowVector);
key.set(i);
writer.append(key,value);
}
writer.close();
}
else{ //其他右矩阵依次将列存储到Seq中
DoubleWritable[] columnVector=new DoubleWritable[matrix[0].length];
for (int i=0;i<matrix[0].length;++i){
for (int j=0;j<matrix.length;++j){
columnVector[j]=new DoubleWritable(0);
columnVector[j].set(matrix[j][i]);
}
value.set(columnVector);
key.set(i);
writer.append(key,value);
}
writer.close(); }
}
finally {
}
System.out.println(matPath+"write done!");
}
}
class DoubleArrayWritable extends ArrayWritable {
public DoubleArrayWritable(){
super(DoubleWritable.class);
}
public String toString(){
StringBuilder sb=new StringBuilder();
for (Writable val:get()){
DoubleWritable doubleWritable=(DoubleWritable)val;
sb.append(doubleWritable.get());
sb.append(",");
}
sb.deleteCharAt(sb.length()-1);
return sb.toString();
}
}

以上使用的.mat文件,程序都可以好好的运行。但是当把文件换成一个B1k2k,也就是一个1000*2000的矩阵文件时,就报空指针的异常,“java.lang.NullPointerException”,具体如下:

提示是在ArrayWritable.write()方法中出现空指针的异常,就开始怀疑是ArrayWritable这个类没写好(也就是怀疑人家有bug,然后就下了hadoop2.6.4,还是不行),然后一路追查,到最后ArrayWritable的write()方法最终调用了BufferedOutputStream.write(),然后就开始是open-jdk的不兼容了,然后就重装了sun JDK。还是不行,然后就把java的io包里的.java源码拷贝到工程里,想着单步调试到BufferedOutputStream.write(),看看究竟发生了什么,怎奈jmatio需要用到io包,我又不行重新编译,所以就想先把.mat转化为.txt文件,但是呢,没成功,因为虚拟机磁盘空间不够了,没法了,想想是不是机子环境的问题呢(哈哈哈,想象力太好),就传给谷总试试看能不能运行,谷总说你确定不是算法问题?答:不该呀。呵呵呵,结果谷总发来了两张图片,如下:

至此,终于找到了原因,就是代码有问题。columnVector数组是用来存储矩阵的一列,数组长度矩阵的行数,但是原先的代码里却将数组长度定义为矩阵的列数。

 DoubleWritable[] columnVector=new DoubleWritable[matrix[0].length];
for (int i=0;i<matrix[0].length;++i){
for (int j=0;j<matrix.length;++j){
columnVector[j]=new DoubleWritable(0);
columnVector[j].set(matrix[j][i]);
}
value.set(columnVector);
key.set(i);
writer.append(key,value);
}

这就解释了,为什么1k*1100的矩阵转化时会提示空指针异常,按照上述对columnVector的定义,这个列向量数组的长度是1100,但是在接下来给这个向量赋值时,是由矩阵的行数来控制,也就是说在赋值时只是对columnVector复制到第1000个元素,剩下的100个元素是空(如果是系统的基本类型,如int double,编译器会将其置为0,不过DoubleWritable不是基本类型),也就是“null”,所以在接下来使用writer.append(key,vlaue)调用输出流写出的时候,自然会抛出“java.lang.NullPointerException”异常。经过修改的代码如下:

 /**
* Created with IntelliJ IDEA.
* User: hadoop
* Date: 16-3-6
* Time: 上午10:56
* To change this template use File | Settings | File Templates.
*/
//package java.io;
import com.jmatio.io.MatFileReader;
import com.jmatio.types.*;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
public class mat2Seq {
public static void main(String[] args) throws IOException {
writeMat2Seq("data/1k_1k/F1k1k.mat","SeqOutput/F1k1k");
writeMat2Seq("data/100_100/b100.mat","SeqOutput/b100");
writeMat2Seq("data/1k1100/mat1k1100.mat","SeqOutput/test1k1100");
writeMat2Seq("data/B1k2w.mat","SeqOutput/1k2w"); //writeMat2Seq("data/1k_2w/B1k2w.mat","SeqOutput5/B1k2w");
} public static void writeMat2Seq(String matPath,String SeqOutput) throws IOException {
MatFileReader reader=new MatFileReader(matPath);
MLArray mlArray=reader.getMLArray("a");
MLDouble doubleValue=(MLDouble)mlArray;
double[][] matrix=doubleValue.getArray();
Configuration conf =new Configuration();
//FileSystem fs=FileSystem.get(URI.create(SeqOutput),conf);
FileSystem fs=FileSystem.get(conf);
Path path=new Path(SeqOutput);
//FSDataOutputStream outputStream=fs.create(path);
IntWritable key=new IntWritable();
DoubleArrayWritable value=new DoubleArrayWritable();
SequenceFile.Writer writer=null;
try {
writer=SequenceFile.createWriter(fs,conf,path,key.getClass(),value.getClass()); // SequenceFile.Writer.Option
if (matPath.endsWith("F1k.mat")){ //左矩阵F依次将行存储到Seq
DoubleWritable[] rowVector=new DoubleWritable[matrix[0].length];
for (int i=0;i<matrix.length;++i){
for (int j=0;j<matrix[0].length;++j){
rowVector[j]=new DoubleWritable(0);
rowVector[j].set(matrix[i][j]);
}
value.set(rowVector);
key.set(i);
writer.append(key,value);
}
writer.close();
//outputStream.close();
fs.close();
}
else{ //其他右矩阵依次将列存储到Seq中
//DoubleWritable[] columnVector=new DoubleWritable[matrix[0].length];
DoubleWritable[] columnVector=new DoubleWritable[matrix.length];
for (int i=0;i<matrix[0].length;++i){
for (int j=0;j<matrix.length;++j){
columnVector[j]=new DoubleWritable(0);
columnVector[j].set(matrix[j][i]);
}
value.set(columnVector);
key.set(i);
writer.append(key,value);
}
writer.close();
//outputStream.close();
fs.close(); }
}
finally {
}
System.out.println(matPath+"write done!");
}
}
class DoubleArrayWritable extends ArrayWritable {
public DoubleArrayWritable(){
super(DoubleWritable.class);
}
/*
public String toString(){
StringBuilder sb=new StringBuilder();
for (Writable val:get()){
DoubleWritable doubleWritable=(DoubleWritable)val;
sb.append(doubleWritable.get());
sb.append(",");
}
sb.deleteCharAt(sb.length()-1);
return sb.toString();
}
*/
}

另外,就是把DoubleArrayWritable的toString()方法注释掉是有原因的,如果使用这个新定义的toString()方法,写入SequenceFile中的value形式就是0.344,0.435......,这种矩阵形式(使用hadoop fs -text),形式一目了然,但是文件写入速度慢(B1k2w文件需要两分钟才可以完成)。如果使用Object提供的toString()方法的话,写入的value形式就是DoubleArrayWritable@34d79f形式,看着不直观,如果要查看value的值还必须使用程序反序列化,但是这种方法写入的内容很少,文件的写入速度很快(B1k2w文件只需要1~2s就可完成)。所以还是不要重载toString()方法。

记一次深刻的教训-----将mat数据转化为SequenceFile的更多相关文章

  1. opencv MAT数据操作

    1.存取单个像素值 最通常的方法就是 img.at<uchar>(i,j) = 255; img.at<Vec3b>(i,j)[0] = 255; 2.用指针扫描一幅图像 对于 ...

  2. 两分钟解决Python读取matlab的.mat数据

    Matlab是学术界非常受欢迎的科学计算平台,matlab提供强大的数据计算以及仿真功能.在Matlab中数据集通常保存为.mat格式.那么如果我们想要在Python中加载.mat数据应该怎么办呢?所 ...

  3. 【转】Java读取matlab的.mat数据文件

    参考:Java读取mat文件 下载链接:ujmp  jmatio 下载完两个.jar文件之后,如何引用到java项目当中?项目名称->右键->Property->Java Build ...

  4. OpenCV几种访问cv::Mat数据的方法

    一般来说,如果是遍历数据的话用指针ptr比用at要快.特别是在debug版本下.因为debug中,OpenCV会对at中的坐标检查是否有溢出,这是非常耗时的. 代码如下 #include <op ...

  5. opencv-从图像旋转学习Mat数据訪问

    先看一个简单的样例 代码: // ConsoleApplication3_6_23.cpp : Defines the entry point for the console application. ...

  6. OpenCV中Mat数据的访问报错

    最近再写一段程序的时候,要访问Mat中的元素.在定义Mat型数据的时候,用 Mat ObjectPoints(48,3,CV_32FC1,0) 对其进行初始化后,用at进行访问时报内存错误. Mat ...

  7. 转 OpenCV Mat 数据读写

    转:https://blog.csdn.net/u011520181/article/details/83831866 1.创建 Mat 对象: // 创建一个 320x240 的 8 位无符号型 4 ...

  8. c++读写matlab中.mat数据

    前言:在进行图形图像处理时,经常会用到matlab进行算法的仿真验证,然后再移植到别的语言中.有时会涉及到数据的交互,比如直接读取matlab的.mat类型数据,或者是将c++中的数组存为.mat,为 ...

  9. 记一次利用AutoMapper优化项目中数据层到业务层的数据传递过程。

    目前项目中获取到DataSet数据后用下面这种方式复制数据. List<AgreementDoc> list = new List<AgreementDoc>(); ].Row ...

随机推荐

  1. 使用MAT分析内存泄露

    使用MAT分析内存泄露 对于大型服务端应用程序来说,有些内存泄露问题很难在测试阶段发现,此时就需要分析JVM Heap Dump文件来找出问题.随着单机内存越来越大,应用heap也开得越来越大,动辄十 ...

  2. IDEA2017 使用(二)

    1.鼠标悬浮在方法上显示api 2.关闭拼写检查 3.自动导入包(存在多个包时需要手动导入) 4.设置方法线

  3. 接口认证方式:Bearer Token

    因为HTTP协议是开放的,可以任人调用.所以,如果接口不希望被随意调用,就需要做访问权限的控制,认证是好的用户,才允许调用API. 目前主流的访问权限控制/认证模式有以下几种: 1),Bearer T ...

  4. SpringMVC学习 -- 使用 @RequestMapping 映射请求

    在控制器的类定义及方法出定义出都可以标注 @RequestMapping: 类定义处:提供初步的请求映射信息.相对于 Web 应用的根目录. 方法定义出:提供进一步的细分映射信息.相对于类定义处的 U ...

  5. Sencha Touch2 -- 11.1:定义具有关联关系的模型

    在Sencha Touch2.0中,可以定义不同模型之间的关联关系.例如,在开发博客网站的时候,可以首先定义用户(User)模型,然后为用户定义文章(Article)模型.一个用户可以发表多篇文章,因 ...

  6. Java类的声明和访问介绍

    1.类的声明 类本身的声明:对类的声明来说,主要包括类的访问权限声明和非访问修饰符的使用.对于一个普通的Java类(POJO)来说,主要的访问权限修饰符只有两个public和默认权限,内部类可以有pr ...

  7. jsonp解析 html

    https://jsoup.org/cookbook/  官网的教程, 很详细! <dependency> <groupId>org.jsoup</groupId> ...

  8. Git菜鸟

    1.git 和svn的差异 git和svn 最大的差异在于git是分布式的管理方式而svn是集中式的管理方式.如果不习惯用代码管理工具,可能比较难理解分布式管理和集中式管理的概念.下面介绍两种工具的工 ...

  9. 学习正则表达式及c#应用

    1.0正则表达式语法   正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”).模式描述在搜索文本时要匹配的一个或多个字符串. 正则表达式示例   表达式 ...

  10. bzoj 3100 排列

    题目大意: 给你长度为 \(1e6\) 的序列, 求最大的 \(K\) 使得序列中含有一个 \(K\) 的排列 做法: 性质: 区间包含1, 元素不重, 区间最大值=区间长度 枚举一个 \(1\) 让 ...