使用Apache POI从字符串中读取Excel文件

5
我正在尝试使用Apache POI 3.9从字符串中读取Excel文件,但没有成功。我对Java并不太熟悉。
仅做澄清,在我的程序中,我已经将Excel文件作为字符串拥有,并通过使用readFile函数来模拟该行为。
程序:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class Test {

    static String readFile(String path, Charset encoding) throws IOException 
    {
        byte[] encoded = Files.readAllBytes(Paths.get(path));
        return encoding.decode(ByteBuffer.wrap(encoded)).toString();
    }

    public static void main(String[] args) throws IOException, InvalidFormatException {
        String result = readFile("data.xlsx", StandardCharsets.UTF_8);

        InputStream is = new ByteArrayInputStream(result.getBytes("UTF-8"));

        Workbook book = WorkbookFactory.create(is);
    }

}

我收到的错误信息是:
Exception in thread "main" java.util.zip.ZipException: invalid block type
    at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
    at java.util.zip.ZipInputStream.read(ZipInputStream.java:193)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource$FakeZipEntry.<init>(ZipInputStreamZipEntrySource.java:127)
    at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:55)
    at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:83)
    at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:267)
    at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:73)
    at Test.main(Test.java:28)

任何帮助都将不胜感激。

谢谢。


你可能会发现这个库很有用:https://github.com/eaorak/excelr - koders
4个回答

8
所以,我问题的解决方法是:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class Test {

    public static void main(String[] args) throws IOException, InvalidFormatException {
        byte[] result = Files.readAllBytes(Paths.get("data.xlsx"));     
        InputStream is = new ByteArrayInputStream(result);
        Workbook book = WorkbookFactory.create(is);
    }

}

你为什么要这样做?正如文档所解释的那样,通过流进行操作比直接使用文件占用更多内存 - Gagravarr
2
我这么做的原因是因为我在一个 Web 服务中获取了这个文件。 - ducky

4
看起来你把这个问题想得太复杂了。只需按照Apache POI快速指南的建议,使用FileInputStream读取文件即可。无需将字节读入字节数组并使用ByteArrayInputStream
可以使用以下代码,从指南中复制而来:
// Use a file
Workbook wb = WorkbookFactory.create(new File("MyExcel.xls"));

// Use an InputStream, needs more memory
Workbook wb = WorkbookFactory.create(new FileInputStream("MyExcel.xlsx"));

我已经对我的问题进行了澄清。 - ducky
2
不清楚您为什么认为在创建“工作簿”之前需要将文件内容转换为“字符串”。您无需这样做。 - rgettman
我同意。但在我的程序中,我想要在一些代码上建立一个抽象层。我认为String可能不是最好的选择,使用InputStream会更好。 - ducky

0
这个问题困扰了我一段时间。所有建议的修复方法都对我无效。解决问题的方法是在maven-resources-plugin中添加一个<useDefaultDelimiters>元素。
        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.5</version>
            <configuration>
              <encoding>UTF-8</encoding>
              <nonFilteredFileExtensions>
                <nonFilteredFileExtension>docx</nonFilteredFileExtension>
                <nonFilteredFileExtension>xls</nonFilteredFileExtension>
                <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
              </nonFilteredFileExtensions>
            </configuration>
        </plugin>   

0
你在做什么?你正在将一个二进制文件读入到一个byte[]中,并使用UTF-8将其转换为String。然后,你又将其使用UTF-8转换回字节流。这样做的目的是什么?跳过所有中间步骤:
public static void main(String[] args) throws IOException, InvalidFormatException {
    InputStream is = new FileInputStream("data.xlsx");
    Workbook book = WorkbookFactory.create(is);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接