2012-06-21 57 views
7

Tôi đang sử dụng thư viện Apache POI 3.8 để đọc tệp XLSX trong ứng dụng web. Các mã sau đây làm việc hoàn toàn tốt đẹp từ một giao diện điều khiển ứng dụng Java:Lỗi khi đọc Excel .XLSX với Apache POI

InputStream inputFS = new FileInputStream("test.xlsx"); 
Workbook workbook = new XSSFWorkbook(inputFS); // below exception is thrown on this line 
Sheet sheet = workbook.getSheetAt(0); 

nhưng ném một "đọc lỗi" khi được sử dụng trong các ứng dụng web. Một chiết xuất có liên quan của stack trace được dán bên dưới:

java.io.IOException: Read error 
at java.io.FileInputStream.readBytes(Native Method) ~[na:1.6.0_31] 
at java.io.FileInputStream.read(Unknown Source) ~[na:1.6.0_31] 
at java.io.FilterInputStream.read(Unknown Source) ~[na:1.6.0_31] 
at java.io.PushbackInputStream.read(Unknown Source) ~[na:1.6.0_31] 
at java.util.zip.ZipInputStream.readFully(Unknown Source) ~[na:1.6.0_31] 
at java.util.zip.ZipInputStream.readLOC(Unknown Source) ~[na:1.6.0_31] 
at java.util.zip.ZipInputStream.getNextEntry(Unknown Source) ~[na:1.6.0_31] 
at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:51) ~[poi-ooxml-3.8-20120326.jar:3.8] 
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:83) ~[poi-ooxml-3.8-20120326.jar:3.8] 
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:228) ~[poi-ooxml-3.8-20120326.jar:3.8] 
at org.apache.poi.util.PackageHelper.open(PackageHelper.java:39) ~[poi-ooxml-3.8-20120326.jar:3.8] 
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:187) ~[poi-ooxml-3.8-20120326.jar:3.8] 
at com.corp.ReportManager.parseExcelReport(ReportManager.java:575) [ReportManager.class:na] 

Các lọ sau đây được bao gồm trong classpath (theo thứ tự):

poi-3.8-20120326.jar 
poi-ooxml-3.8-20120326.jar 
poi-ooxml-schemas-3.8-20120326.jar 
xbean.jar 
dom4j-1.6.1.jar 

Hiện không có vẻ là một vấn đề bộ nhớ liên quan kể từ khi tôi thu thập một số thống kê sử dụng heap ngay trước khi gọi mã trên. Tệp XLSX có kích thước 1,15 MB.

##### Heap utilization statistics [MB] ##### 
Used Memory:13 MB 
Free Memory:9 MB 
Total Memory:23 MB 
Max Memory:247 MB 
+1

có thể xem ứng dụng web của bạn/sửa đổi các tập tin của bạn đọc từ đâu? –

+0

Ứng dụng web có quyền truy cập vào tệp, nếu đó là những gì bạn đang yêu cầu. Nó chỉ đọc (không sửa đổi). Trên một lưu ý liên quan, ứng dụng web xử lý các tệp XLS (định dạng nhị phân cũ hơn) mà không có vấn đề. Nó chỉ với các tập tin XLSX mà nó chạy vào một vấn đề. –

+0

có bất kỳ tính năng mới nào đang được sử dụng mà nó không hỗ trợ không? http://poi.apache.org/spreadsheet/index.html –

Trả lời

5

Phương pháp sử dụng mã trên có một thông số duy nhất - FileInputStream. Dòng đầu tiên trong đoạn mã là phần rất nhiều của mã, nhưng là một phần của phương thức gọi. Kể từ khi phương pháp trong câu hỏi không có kiến ​​thức về định dạng Excel hoặc thậm chí một phần mở rộng tập tin để đoán được đào tạo, tôi đã quyết định rằng đầu tiên tôi sẽ cố gắng để đọc FileInputStream sử dụng API HSSF như sau:

Sheet sheet = null; 
try { 

    POIFSFileSystem poifs = new POIFSFileSystem(inputFS); 
    Workbook workbook = new HSSFWorkbook(poifs); 
    sheet = workbook.getSheetAt(0); 
} 
catch (Exception e) { 
} 

if (sheet == null) { 

    try { 

     Workbook workbook = new XSSFWorkbook(inputFS); 
     sheet = workbook.getSheetAt(0); 
    } 
    catch (Exception e) { 
    } 
} 

Vấn đề với mã trên là trạng thái của đối tượng inputFS trong lần thử thứ hai mở nó thông qua API XSSF là không xác định. Và điều này mang lại một số read error. Tôi thay thế trên bằng đoạn mã sau, trong đó hoạt động tốt và vấn đề này dường như được giải quyết:

Sheet sheet = null; 
try { 

    Workbook workbook = WorkbookFactory.create(inputFS); 
    sheet = workbook.getSheetAt(0); 
} 
catch (Exception e) { 
} 

Tôi đã thử nghiệm điều này với cả hai XLS (cũ, nhị phân) và (mới hơn, dựa trên XML) định dạng XLSX và nó công trinh. Cảm ơn sự giúp đỡ và đầu vào của mọi người!

1

có vẻ như bạn cần phải sử dụng họ XSSF API

+0

Tôi đang sử dụng API XSSF của họ thông qua API SS. Như tôi đã nói trước đó, chính xác cùng một mã hoạt động tốt trong một ứng dụng giao diện điều khiển. Đây là ứng dụng web có sự cố khi thực thi dòng thứ hai trong mã. –

+0

Và bạn có thể làm việc với định dạng cũ hơn từ một ứng dụng web? Có vẻ như bạn sẽ không thể truy cập tệp vì bất kỳ lý do nào hoặc bạn không thể đọc định dạng mà nó đang sử dụng. –

+1

Có vẻ như họ đang sử dụng XSSFReader trong mã ví dụ của họ mà bạn không làm. Tuy nhiên, điều đó không giải thích lý do tại sao nó sẽ làm việc trong một ứng dụng giao diện điều khiển ... Trong đó cung cấp hỗ trợ nhiều hơn cho nó là một vấn đề cho phép. Có thể thử xem ứng dụng của bạn có thể xem/đọc nó không? –

2

Ngoại lệ chỉ ra rằng có điều gì đó với InputStream của bạn. Tuy nhiên, nếu bạn có một tập tin, sau đó chuyển nó vào POI trực tiếp !. Sử dụng InputStream đòi hỏi phải đệm tất cả mọi thứ vào bộ nhớ, sẽ chiếm không gian. Vì bạn không cần phải làm điều đó đệm, không! Tránh việc đệm đó phải khắc phục sự cố của bạn anyway

Nếu bạn đang chạy với bản dựng POI hàng đêm mới nhất thì rất dễ dàng. Mã của bạn trở thành:

File file = new File("test.xlsx"); 
OPCPackage opcPackage = OPCPackage.open(file); 
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage); 

Nếu không, nó rất giống:

File file = new File("test.xlsx"); 
OPCPackage opcPackage = OPCPackage.open(file.getAbsolutePath()); 
XSSFWorkbook workbook = new XSSFWorkbook(opcPackage); 

Nếu bạn không chắc chắn nếu tập tin của bạn là một HSSFWorkbook hoặc XSSFWorkbook, sau đó bạn có thể sử dụng WorkbookFactory để mở một thích hợp cho bạn:

File file = new File("test.xlsx"); 
Workbook workbook = WorkbookFactory.create(file); 
+0

Có, tôi đã kết thúc bằng cách sử dụng 'WorkbookFactory.create (...)' vì tôi không biết liệu tệp đó là HSSFWorkbook hay XSSFWorkbook. –

+1

Đảm bảo bạn sử dụng phiên bản Tệp thay vì phiên bản InputStream nếu bạn có đối tượng Tệp thực - nó sẽ nhanh hơn và thấp hơn bộ nhớ! – Gagravarr

+0

tại sao tôi nhận được 'java.lang.ClassNotFoundException: org.apache.poi.ss.usermodel.WorkbookFactory', khi tôi có tất cả các jars trong lib? (NetBeans) – victorio

-3

sử dụng jar này

<dependency> 
    <groupId>org.apache.xmlbeans</groupId> 
    <artifactId>xmlbeans</artifactId> 
    <version>2.3.0</version> 
</dependency> 
Các vấn đề liên quan