Apache POI - 读取修改后的Excel文件

6
无论何时我使用Apatche POI打开一个Excel文件,即使我只是读取文件而没有进行任何修改,该文件也会被修改。
例如以下测试代码。
public class ApachePoiTest {

    @Test
    public void readingShouldNotModifyFile() throws Exception {
        final File testFile = new File("C:/work/src/test/resources/Book2.xlsx");
        final byte[] originalChecksum = calculateChecksum(testFile);
        Assert.assertTrue("Calculating checksum modified file",
            MessageDigest.isEqual(originalChecksum, calculateChecksum(testFile)));
        try (Workbook wb = WorkbookFactory.create(testFile)) {
            Assert.assertNotNull("Reading file with Apache POI", wb);
        }
        Assert.assertTrue("Reading file with Apache POI modified file",
            MessageDigest.isEqual(originalChecksum, calculateChecksum(testFile)));
    }

    @Test
    public void readingInputStreamShouldNotModifyFile() throws Exception {
        final File testFile = new File("C:/work/src/test/resources/Book2.xlsx");
        final byte[] originalChecksum = calculateChecksum(testFile);
        Assert.assertTrue("Calculating checksum modified file",
            MessageDigest.isEqual(originalChecksum, calculateChecksum(testFile)));
        try (InputStream is = new FileInputStream(testFile); Workbook wb = WorkbookFactory.create(is)) {
            Assert.assertNotNull("Reading file with Apache POI", wb);
        }
        Assert.assertTrue("Reading file with Apache POI modified file",
            MessageDigest.isEqual(originalChecksum, calculateChecksum(testFile)));
    }

    private byte[] calculateChecksum(final File file) throws Exception {
        final MessageDigest md = MessageDigest.getInstance("MD5");
        md.reset();
        try (InputStream is = new FileInputStream(file)) {
            final byte[] bytes = new byte[2048];
            int numBytes;
            while ((numBytes = is.read(bytes)) != -1) {
                md.update(bytes, 0, numBytes);
            }
            return md.digest();
        }
    }
}

测试readingShouldNotModifyFile的结果总是失败的,因为Apache POI始终会修改文件。更糟糕的是,在使用MS Office创建空白Excel文件进行测试时,Apache POI会将文件从8.1 kb裁剪到6.2 kb并破坏文件的完整性。

测试使用的环境:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.15</version>
</dependency>

同时还有版本3.12。

我能否通过其他方式防止Apache POI修改我的文件,而不是传递InputStream而不是File。我不想传递InputStream,因为我担心Apache的警告会占用更多内存,并且对InputStream有一些特定要求。

1个回答

9
你的问题是没有传入readonly标志,因此Apache POI默认打开文件的读/写权限。
你需要使用重载的WorkbookFactory.create方法,该方法带有只读标志+将只读标志设置为true 更改该行
try (InputStream is = new FileInputStream(testFile); Workbook wb = WorkbookFactory.create(is)) {

try (IWorkbook wb = WorkbookFactory.create(testFile,null,true)) {

你的文件将以只读模式打开,不会进行任何更改。


我一定是瞎了,因为我不知怎么错过了那个重载的方法。谢谢你指出来 :) - MJar

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