一个下午,找了一条小虫,JAVA读取fits文件出错异常

准备用JAVA完成对光谱的读取,并寻找相似集。下午开始,就卡在光谱的读取中,郁闷了一个下午。以前用MATLAB写过读取光谱的代码(FIT文件格式解析及MATLAB读取程序),也用C++写过,但是觉得C++以前一个字节一个自己的读取过于麻烦,所以对于JAVA的,先找找是不是有读取fits文件的包。没想到还找到了:Java Library for access to FITS files 。但是,后来问题来了:

开始我用v2..3版本的fits数据,读取文件都没问题,对于关键字的读取很顺利。后来想着现在的pipeline都是2.6版本的了,所以还是重新下载了新版本的数据,但是问题来了,一直显示不是fits文件。但是我用fv打开一切都正常。后来下了dr8的数据,也没发现问题,说明这个包的兼容性还是可以的,但是不知道为什么出现问题。

首先,我想到是不是因为数据的事,后来重新下载了2.6版本的其他数据,测试,还是一样的问题。而且用fv能正常打开,所以数据的问题应该可以排除。

没办法,只能从包里找问题了,因为pipeline跑出来的数据是没法重新修改的,否则这么大的数据,是整个工程的事。幸好这个Library给出了source文件,把source文件加载了,然后一步一步的调试,F11,F5,F6,F8,System.out.println, 找了很久,跟踪了很久,终于发现问题了。

一个下午,找了一条小虫,JAVA读取fits文件出错异常_第1张图片

肯定是这个keyword出了问题,但是没有明显的差别啊。后来跟踪到源代码的异常处理后发现问题的关键所在:

 public FitsKeyword(byte[] card) throws FitsException {
	int idx = 0;                         // index in FITS card
	int idx_last = 0;                    // last index of value field
	int idx_comm_first = 0;              // first index of comment field

	// if card is null or too short - add spaces
	if (card == null || card.length < Fits.CARD) {
	    byte[] pc = new byte[Fits.CARD];
	    int n = 0;
	    while (n < card.length) {
		pc[n] = card[n];
		n++;
	    }
	    while (n < Fits.CARD) pc[n++] = SPACE;
	    card = pc;
	}

	if ((card[0] != SPACE) && (card[0] != MINUS) && (card[0] != UNDERSCORE)
	       && ((card[0] < A) || (Z < card[0])) ) { 
	    throw new FitsException("Illegal character",
				    FitsException.KEYWORD);    
	}

原来,在检查fitskeyword的时候,他会检查card的第一个字符,而出问题的关键字的新版本是1D_CLASS,以1开头,所以抛出了Illegal character的异常导致程序不能运行,进而抛出文件的异常is not a FITS file.


终于找到Bug了,很开心,呵呵,虽然问题很小很小,但是过程是美好的,也进一步对JAVA的调试,包的导入有了更好的理解。另外,在Source中发现这样一段代码:

try {
	    int n = 0;
	    while (true) {
	    //System.out.println(kw.getString());
		for (int k=0; k<Fits.CARD; k++) {
		    line[k] = record[n++];
		}
		kw = new FitsKeyword(line);
		
		keywords.add(kw);
		if (Fits.RECORD <= n) {
		    file.readFully(record, 0, Fits.RECORD);
		    n = 0;
		}
	    }
	} catch (IOException e) {
	    throw new FitsException("Cannot read header",
				    FitsException.HEADER);
	    
	} catch (FitsException e) {
	    if (e.getType() != FitsException.ENDCARD) {
		throw new FitsException("Bad FITS keyword",
					FitsException.HEADER);
		
	    }
	}

开始纳闷的是while循环的判断是true,那什么时候运行是个头呢。呵呵,经过跟踪发现,原来是当readFully后也会抛出一个end的异常,进而对异常处理,这样就退出来了while循环。


总结:遇到问题,一定要理性的去分析,排除原因,一步一步调试,和C++一样,要熟练是使用调试。另外有时间多看看别人写的源码,真的能有很多启发。

你可能感兴趣的:(一个下午,找了一条小虫,JAVA读取fits文件出错异常)