您的位置:首页 > 编程语言 > Java开发

使用JXL生成Excel时发生java.lang.ArrayIndexOutOfBoundsException错误

2010-05-20 15:47 405 查看
错误信息如下:

......

java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at jxl.biff.StringHelper.getBytes(StringHelper.java:127)
at jxl.write.biff.WriteAccessRecord.<init>(WriteAccessRecord.java:59)
at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:726)


......

神奇的是,在项目中发现该现象只有在Linux环境下才发生而Window下则正常运行。

根据错误信息的提示,发现问题出在WriteAccessRecord文件里,其源代码如下所示:

package jxl.write.biff;

import jxl.Workbook;
import jxl.biff.StringHelper;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;

/**
* The name used when Excel was installed.
* When writing worksheets, it uses the value from the WorkbookSettings object,
* if this is not set (null) this is hard coded as
* Java Excel API + Version number
*/
class WriteAccessRecord extends WritableRecordData
{
/**
* The data to output to file
*/
private byte[] data;

// String of length 112 characters
/**
* The author of this workbook (ie. the Java Excel API)
*/
private final static String authorString = "Java Excel API";
private String userName;

/**
* Constructor
*/
public WriteAccessRecord(String userName)
{
super(Type.WRITEACCESS);

data = new byte[112];
String astring = userName != null ?
userName :
authorString + " v" + Workbook.getVersion();

StringHelper.getBytes(astring, data, 0);

// Pad out the record with space characters
for (int i = astring.length() ; i < data.length ;i++)
{
data[i] = 0x20;
}
}

/**
* Gets the data for output to file
*
* @return the binary data
*/
public byte[] getData()
{
return data;
}
}


分析上诉代码发现,byte数组data的最大长度被定义为112,当被传入的参数userName达到一定长度时就会抛错。

跟踪代码WritableWorkbookImpl发现,userName实际就是WorkbookSettings类中的writeAccess字段,亦即生成Excel是的用户信息。可能在linux环境UTF8下每个汉字的字节数为3位(Windows中是2位)的缘故,出现了上诉的奇异现象。

解决的办法如下:

1.修改JXL源代码中WriteAccessRecord文件代码,重新设置变量data的长度,例如:data = new byte[astring.getBytes().length];

2.一般我们在读取模板文件生成新的Excel时往往使用如下代码:

import java.io.File;

import jxl.Workbook;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Test {

public static void main(String[] args) throws Exception {

Workbook wb = Workbook.getWorkbook(new File("C:/data_template.xls"));
WritableWorkbook workbook = Workbook.createWorkbook(new File("C:/data_output.xls"), wb);

WritableSheet sheet = workbook.getSheet(3);
sheet.getSettings().setSelected(true);

workbook.write();
workbook.close();
}
}


只要在代码中强制设置变量WorkbookSettings.writeAccess的值即可,例如:

Workbook wb = Workbook.getWorkbook(new File("C:/data_template.xls"));
WorkbookSettings settings = new WorkbookSettings ();
settings.setWriteAccess(null);

WritableWorkbook workbook = Workbook.createWorkbook(new File("C:/data_output.xls"), wb, settings);

WritableSheet sheet = workbook.getSheet(3);
sheet.getSettings().setSelected(true);

workbook.write();
workbook.close();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: