文章内容:最近使用LeapMotion进行软件开发时,使用到了java API---->List集合,使用过程中遇到了一些小bug,特写此博客记录相关心得。
程序编写背景:使用leapMotion提供的Frame类中的deserialize()函数将byte[]数组值反序列化成Frame对象,并存放至List<Frame>集合中。具体代码参见LeapMotionFrameFileOperation.java中的readFile()函数
javaAPI--->List相关:这个程序中使用到了List<Frame> 集合,下面是从整个程序中抽离出的和List相关的代码部分
。
。
。
List<Frame> frames=new LinkedList<Frame>();//用于存储从文件中序列化数据解析出来的Frame对象
。
。
。
Frame newFrame = new Frame();
System.out.println("下面进行反序列化...");
newFrame.deserialize(frameData);
frames.add(newFrame);
。
。
。
return frames;
bug调试:最开始时,代码中是这样写的
List<Frame> frames=null;
这种情况下,执行到
frames.add(newFrame);时就会抛出如下异常,
Exception in thread "main" java.lang.NullPointerException
at LeapMotionFrameFileOperation.readFile(LeapMotionFrameFileOperation.java:190)
at DisplayFileData.main(DisplayFileData.java:26)
为了修复上述bug,将代码改为
List<Frame> frames=new LinkedList<Frame>();//当然,这里不只这一种改法,可以使用List接口的任何一个实现类的构造函数来初始化List
修改之后bug便不存在了。
附录:LeapMotionFrameFileOperation.java中的readFile()函数
/
* @function read the frame data from the saved file
* @编程思路
* To read the frame data from the saved file,
* you can then read the first 4 bytes of the file to determine
* how much data to read to get an entire frame.
* Simply repeat the process until you reach the end of the file.
* @param path:String 待读取文件的绝对路径 如d:/LeapMotionData/FrameData/gesture1.txt
* @throws IOException */
@SuppressWarnings("null")
public List<Frame> readFile(String path) throws IOException{
System.out.println("进入readFile()函数内部");
List<Frame> frames=new LinkedList<Frame>();//用于存储从文件中序列化数据解析出来的Frame对象
File file=new File(path);
if(!file.exists()&&file.isFile()){
System.out.println("相应的文件并不存在,请检查您给出的文件路径是否正确:"+path);
return null;
}else{//也就是相应文件一定存在的情况下
System.out.println(path+"文件是存在的,下面准备对其进行反序列化...");
Path filePath=Paths.get(path);
byte[] data=Files.readAllBytes(filePath);//将文件中数据一次性读出到一个byte数组中,当文件过大时,要注意内存溢出问题
System.out.println("将上述文件中的内容全部读出,并存放在一个byte[]数组中,数组长度="+data.length);
System.out.print("byte[] data="+data+"\n");
int c=0;//data:byte[]的数组下标,相当于文件指针的当前位置
int f=0;
int nextBlockSize=0;//表示接下来一帧数据的长度(单位为byte)
if(data.length>4){//获得初始的serializedFrame.length:int
/*原本存储序列化后的Frame数据时,为了将来进行反序列化也存储了每个序列化Frame数据帧的数据长度(单位为byte)
* 序列化帧数据长度是一个4 byte 的int值
* 所以反序列化时就要读取4 byte的二进制值,然后使用下面的方法将其转换成十进制数字
*/
nextBlockSize=(data[c++] & 0x000000ff) << 24 |
(data[c++] & 0x000000ff) << 16 |
(data[c++] & 0x000000ff) << 8 |
(data[c++] & 0x000000ff);
System.out.println("nextBlockSize="+nextBlockSize+"\tc="+c);
}
while (c + nextBlockSize <= data.length){
byte[] frameData = Arrays.copyOfRange(data, c, c + nextBlockSize);//取出一帧数据
System.out.println("frameData:byte[] length="+frameData.length);
c += nextBlockSize;//使得数组下标编程下一帧数据 数据长度 位置
Frame newFrame = new Frame();
System.out.println("下面进行反序列化...");
newFrame.deserialize(frameData);//反序列化,有byte数组形式数据转化成Frame Object
System.out.println("反序列化成功,获得一个Frame对象,frame.isvalid()="+newFrame.isValid());
this.diaplayFrameInfo(newFrame);
System.out.println("将上述Frame对象存放到List<Frame>集合中..\nlist.size="+frames.size());
boolean flag=frames.add(newFrame);//将反序列化所得Frame对象添加到List<Frame>中
System.out.println("上述Frame对象已经被添加到List<Frame> frames集合中?"+flag+",frames.size="+frames.size());
if(data.length - c > 4){
nextBlockSize = (data[c++] & 0x000000ff) << 24 |
(data[c++] & 0x000000ff) << 16 |
(data[c++] & 0x000000ff) << 8 |
(data[c++] & 0x000000ff);
}
}//end while
}//end if..else..
return frames;
}//end readFile()