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

时间:2017-01-25 05:49:02

标签: java excel spring apache-poi

我正在使用弹簧读取输入通道,无论哪个文件进来我都在使用它。基本上该文件是excel文件,因此我使用了 apache POI工作簿。 以下是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。对此有任何帮助将非常感激。

1 个答案:

答案 0 :(得分: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.");
    }
}