1. 程式人生 > >java專案從win上佈署到linux上報java.lang.ArrayIndexOutOfBoundsException錯誤

java專案從win上佈署到linux上報java.lang.ArrayIndexOutOfBoundsException錯誤

這種錯誤是我在瀏覽一篇博文上看到的,具體原因是:在linux環境UTF8下每個漢字的位元組數為3位(Windows中是2位)的緣故,出現了上訴的奇異現象。 

這種錯誤是我在瀏覽一篇博文上看到的,具體原因是:在linux環境UTF8下每個漢字的位元組數為3位(Windows中是2位)的緣故,出現了上訴的奇異現象。 

錯誤資訊如下:

......

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檔案裡,其原始碼如下所示:

view plain
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.一般我們在讀取模板檔案生成新的Excel時往往使用如下程式碼:

view plain
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(); 

  轉自:http://lzqdll.blog.163.com/blog/static/200607183201111635447767/