错误信息如下:
......
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/