如何锁定Excel文件以便在Java中进行读写?

问题描述 投票:1回答:1

我正在使用spring读取输入通道,无论输入哪个文件,我都使用相同的格式。基本上文件是excel文件,因此我使用了apache POI workbook。下面是App类

@SpringBootConfiguration
@EnableScheduling
@Component
public class App
{
    public static void main( String[] args ) throws IOException
    {
         SpringApplication.run(App.class, args);
    }

    @Scheduled(fixedRate = 60000)
    public static void displayDirectories () throws InvalidFormatException, IOException{
        ApplicationContext context = new ClassPathXmlApplicationContext("context.xml", App.class);
        File inDir = (File) new DirectFieldAccessor(context.getBean(FileReadingMessageSource.class)).getPropertyValue("directory");
        LiteralExpression expression = (LiteralExpression) new DirectFieldAccessor(context.getBean(FileWritingMessageHandler.class)).getPropertyValue("destinationDirectoryExpression");
        File outDir = new File(expression.getValue());
        System.out.println("Input directory is: " + inDir.getAbsolutePath());
        System.out.println("Archive directory is: " + outDir.getAbsolutePath());
        System.out.println("===================================================");
    }
}

下面是我的bean context.xml中的一些配置:

<file:inbound-channel-adapter id="filesIn"
    directory="file:${java.io.tmpdir}/input">
    <integration:poller id="poller" fixed-rate="60000"/>
</file:inbound-channel-adapter>

<integration:service-activator
    input-channel="filesIn" output-channel="filesOut" ref="handler" />

<file:outbound-channel-adapter id="filesOut"
    directory="file:${java.io.tmpdir}/archive" delete-source-files="true">
</file:outbound-channel-adapter>

<bean id="handler" class="com.practice.Handler" />

下面是我的处理程序类,我试图在该类上获取对excel文件的读取锁定:

@SpringBootConfiguration
@Component
public class Handler {
    FileInputStream fileIn = null;
    FileLock lock = null;
    public File handleFile(File input) {
        try {
            fileIn = new FileInputStream(input);
            lock = fileIn.getChannel().tryLock();
            Workbook filename = WorkbookFactory.create(fileIn);
            .
            /*Some logic*/
            .
        }
        catch(Exception e){
            System.out.println("Exception occured");
            e.printStackTrace();
        }
        finally{
            try {
                lock.release();
                fileIn.close();
            } catch (IOException e) {
                System.out.println("Exception in fileclose or lock");
                e.printStackTrace();
            }
        }
        return input;
    }
}

未实现锁会多次读取我的文件,并且会多次处理它。我的任务是读取一次文件并进行处理,然后将其存档。当我尝试在上述代码中实现锁定时,出现异常java.nio.channels.NonWritableChannelException。但是,建议我将其更改为POIFSFileSystem以解决相同问题。我尝试了谷歌的建议,它们都只建议用于RandomAccessFile。我正在为项目使用Spring Boot。在这方面的任何帮助将不胜感激。

java excel spring apache-poi
1个回答
0
投票

我们可以锁定文件,对其进行读取,修改工作表并进行写入,然后释放锁定。那是一个重要的用例。每个电子表格程序都是这样工作的。

使用Apache POI 4.1.1的有效测试用例:

public static void main(String[] args) throws Exception{
    File testFile = new File("src/main/resources/test.xls");
    if(! testFile.exists()){
        throw new FileNotFoundException(testFile.getAbsolutePath());
    }
    RandomAccessFile randomAccessFile = new RandomAccessFile(testFile, "rw");
    FileChannel fileChannel = randomAccessFile.getChannel();
    FileLock fileLock = fileChannel.tryLock();
    if(fileLock == null){
        throw new NullPointerException("Cannot get lock.");
    }
    boolean readOnly = false;
    POIFSFileSystem filesystem = new POIFSFileSystem(fileChannel, readOnly);
    HSSFWorkbook workbook = new HSSFWorkbook(filesystem);
    workbook.write();
    fileLock.release();
    workbook.close();
    if(!testFile.delete()){
        throw new RuntimeException("Could not delete test file.");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.