Linux环境下 使用JXL生成Excel时发生java.lang.ArrayIndexOutOfBoundsException

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文件里,其源代码如下所示:

[java]  view plain copy
  1. package jxl.write.biff;  
  2.   
  3. import jxl.Workbook;  
  4. import jxl.biff.StringHelper;  
  5. import jxl.biff.Type;  
  6. import jxl.biff.WritableRecordData;  
  7.   
  8. /** 
  9.  * The name used when Excel was installed.   
  10.  * When writing worksheets, it uses the value from the WorkbookSettings object, 
  11.  * if this is not set (null) this is hard coded as 
  12.  * Java Excel API + Version number 
  13.  */  
  14. class WriteAccessRecord extends WritableRecordData  
  15. {  
  16.   /** 
  17.    * The data to output to file 
  18.    */  
  19.   private byte[] data;  
  20.   
  21.   // String of length 112 characters  
  22.   /** 
  23.    * The author of this workbook (ie. the Java Excel API) 
  24.    */  
  25.   private final static String authorString = "Java Excel API";  
  26.   private String userName;  
  27.   
  28.   /** 
  29.    * Constructor 
  30.    */  
  31.   public WriteAccessRecord(String userName)  
  32.   {  
  33.     super(Type.WRITEACCESS);  
  34.   
  35.     data = new byte[112];  
  36.     String astring = userName != null ?  
  37.         userName :  
  38.         authorString + " v" + Workbook.getVersion();  
  39.   
  40.     StringHelper.getBytes(astring, data, 0);  
  41.   
  42.     // Pad out the record with space characters  
  43.     for (int i = astring.length() ; i < data.length ;i++)  
  44.     {  
  45.       data[i] = 0x20;  
  46.     }  
  47.   }  
  48.   
  49.   /** 
  50.    * Gets the data for output to file 
  51.    *  
  52.    * @return the binary data 
  53.    */  
  54.   public byte[] getData()  
  55.   {  
  56.     return data;  
  57.   }  
  58. }  

分析上诉代码发现,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.修改代码,不使用WriteAccessRecord。在读取模板文件生成新的Excel时往往使用如下代码:

[java]  view plain copy
  1. import java.io.File;  
  2.   
  3. import jxl.Workbook;  
  4. import jxl.write.WritableSheet;  
  5. import jxl.write.WritableWorkbook;  
  6.   
  7. public class Test {  
  8.   
  9.     public static void main(String[] args) throws Exception {  
  10.   
  11.         Workbook wb = Workbook.getWorkbook(new File("C:/data_template.xls"));  
  12.         WritableWorkbook workbook = Workbook.createWorkbook(new File("C:/data_output.xls"), wb);  
  13.           
  14.         WritableSheet sheet = workbook.getSheet(3);  
  15.         sheet.getSettings().setSelected(true);  
  16.           
  17.         workbook.write();  
  18.         workbook.close();  
  19.     }  
  20. }  

只要在代码中强制设置变量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(); 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值