如何在Java中实现等待文件修改后再读取数据的功能?

简介: 如何在Java中实现等待文件修改后再读取数据的功能?

文件是计算机系统中重要的存储媒介,常用于存储数据和程序。在Java中,文件操作是非常常见的操作之一。有时候,我们需要在文件被修改后再读取其中的数据,但是文件是一直存在的,并不能通过是否生成去判断,这就需要我们在Java中实现等待文件修改后再读取数据的功能。本文将介绍如何使用Java实现该功能。

一、问题描述

这段代码的作用是将一个Excel表格中的数据提取出来,并以字符串的形式返回。具体实现过程如下:

  1. 根据传入的exePath和tagerPath参数构造出一个命令行字符串,该命令行字符串用于调用外部程序,将Excel表格中的数据提取到一个文本文件中。
  2. 调用Java的Runtime.getRuntime().exec()方法来执行上述命令行字符串,返回一个Process实例,该实例可用来控制进程并获得相关信息。
  3. 读取刚才生成的文本文件中的数据,并将其存储到一个字符数组中。
  4. 将字符数组中的数据转换成字符串,并返回该字符串。
  5. 在finally块中关闭文件流。

E:\ftpTest\data.txt文件文件是一直存在的,并不能通过是否生成去判断,怎么样才能等data.txt文件被exec(run)修改完后再执行读取数据?

public static String tableToBin(String exePath, String tagerPath) {
        String dataPath = "E:\\ftpTest\\data.txt";
        Reader fr = null;
        int length = 0;
        char ch[] = null;
        // Excel.exe test_read.xlsx 文件路径
        String run = exePath + " " + " " + tagerPath + " " + dataPath;
        try {
            //解释:Runtime.getRuntime().exec()方法返回一个Process实例,该实例可用来控制进程并获得相关信息。
            Process proc = Runtime.getRuntime().exec(run);
            System.out.println("读取表格并提取数据完成");
            //读取数据
            fr = new FileReader(dataPath);
            //ch[]数组存放读取的数据
            ch = new char[1024];
            //length为读取的数据长度
            length = fr.read(ch);
            //返回读取的数据
            return new String(ch, 0, length);
        } catch (IOException e) {
            //抛出运行时异常
            throw new RuntimeException(e);
        } finally {
            try {
                //关闭流
                fr.close();
            } catch (IOException e) {
                //抛出运行时异常
                throw new RuntimeException(e);
            }
        }
    }

二、问题分析

如果文件是一直存在的,那么可以通过比较文件的修改时间来判断文件是否更新。可以使用Java的File类的lastModified()方法获取文件的最后修改时间,然后将其与上一次检查时的时间进行比较。如果文件的最后修改时间比上一次检查时的时间要晚,那么说明文件已经更新,可以执行发送数据的代码。你可以在一个循环中不断检查文件是否更新,如果文件更新了就执行发送数据的代码。

三、解决方案

1. 使用Java的File类的lastModified()方法

使用Java的File类的lastModified()方法获取文件的最后修改时间,然后将其与上一次检查时的时间进行比较。如果文件的最后修改时间比上一次检查时的时间要晚,那么说明文件已经更新,可以执行读取数据的代码。

示例代码:

public static String tableToBin(String exePath, String tagerPath) {
    String dataPath = "E:\\ftpTest\\data.txt";
    Reader fr = null;
    int length = 0;
    char ch[] = null;
    long lastModified = 0;
    boolean fileUpdated = false;
    // Excel.exe test_read.xlsx 文件路径
    String run = exePath + " " + " " + tagerPath + " " + dataPath;
    try {
        //解释:Runtime.getRuntime().exec()方法返回一个Process实例,该实例可用来控制进程并获得相关信息。
        Process proc = Runtime.getRuntime().exec(run);
        //等待文件生成
        while(!fileUpdated) {
            File file = new File(dataPath);
            long currentModified = file.lastModified();
            if(currentModified > lastModified) {
                lastModified = currentModified;
                Thread.sleep(1000); //等待1秒
            } else {
                fileUpdated = true;
            }
        }
        //读取数据
        fr = new FileReader(dataPath);
        //ch[]数组存放读取的数据
        ch = new char[1024];
        //length为读取的数据长度
        length = fr.read(ch);
        //返回读取的数据
        return new String(ch, 0, length);
    } catch (IOException e) {
        //抛出运行时异常
        throw new RuntimeException(e);
    } catch (InterruptedException e) {
        //抛出运行时异常
        throw new RuntimeException(e);
    } finally {
        try {
            //关闭流
            fr.close();
        } catch (IOException e) {
            //抛出运行时异常
            throw new RuntimeException(e);
        }
    }
}

在这个示例代码中,我们将文件的最后修改时间与上一次检查时的时间进行比较,如果文件的最后修改时间比上一次检查时的时间要晚,那么说明文件已经更新,可以执行读取数据的代码。如果文件还没有更新,我们使用Java的Thread.sleep()方法等待一段时间,然后再次检查文件的最后修改时间。当文件的最后修改时间不再更新时,我们退出等待循环,执行读取数据的代码。

2. 使用Java的WatchService类

Java的WatchService类可以用于监控文件的变化,并在文件发生变化后再读取数据。使用WatchService类需要创建一个WatchService实例,并将其注册到需要监控的目录上。当目录中的文件发生变化时,WatchService会接收到通知,我们可以在通知中执行读取数据的代码。

示例代码:

public static String readFileAfterUpdate(String filePath) {
    Reader fr = null;
    int length = 0;
    char ch[] = null;
    try {
        //创建WatchService实例
        WatchService watchService = FileSystems.getDefault().newWatchService();
        //将目录注册到WatchService中
        Path path = Paths.get(filePath).getParent();
        path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
        //等待目录中的文件发生变化
        WatchKey watchKey = watchService.take();
        while(watchKey != null) {
            for(WatchEvent<?> event : watchKey.pollEvents()) {
                //如果文件发生变化
                if(event.kind() == StandardWatchEventKinds.ENTRY_MODIFY && event.context().toString().equals(Paths.get(filePath).getFileName().toString())) {
                    //读取数据
                    fr = new FileReader(filePath);
                    ch = new char[1024];
                    length = fr.read(ch);
                    return new String(ch, 0, length);
                }
            }
            watchKey.reset();
            watchKey = watchService.take();
        }
        return null;
    } catch (IOException e) {
        throw new RuntimeException(e);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } finally {
        try {
            fr.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这个示例代码中,我们创建了一个WatchService实例,并将需要监控的目录注册到WatchService中。当目录中的文件发生变化时,WatchService会接收到通知,我们可以在通知中执行读取数据的代码。注意,我们需要在通知中判断文件是否为需要读取的文件。


目录
相关文章
|
13天前
|
Java 程序员 容器
Java中的变量和常量:数据的‘小盒子’和‘铁盒子’有啥不一样?
在Java中,变量是一个可以随时改变的数据容器,类似于一个可以反复打开的小盒子。定义变量时需指定数据类型和名称。例如:`int age = 25;` 表示定义一个整数类型的变量 `age`,初始值为25。 常量则是不可改变的数据容器,类似于一个锁死的铁盒子,定义时使用 `final` 关键字。例如:`final int MAX_SPEED = 120;` 表示定义一个名为 `MAX_SPEED` 的常量,值为120,且不能修改。 变量和常量的主要区别在于变量的数据可以随时修改,而常量的数据一旦确定就不能改变。常量主要用于防止意外修改、提高代码可读性和便于维护。
|
10天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
38 2
|
14天前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
35 2
|
14天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
25 2
|
18天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
40 2
|
23天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
24天前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
33 4
|
Java C语言 C++
Java 的数据类型划分(数据类型划分)| 学习笔记
快速学习 Java 的数据类型划分(数据类型划分)
122 0
Java 的数据类型划分(数据类型划分)| 学习笔记
|
Java 开发者 Windows
Java 数据类型划分(字符型)|学习笔记
快速学习 Java 数据类型划分(字符型)
127 0
|
Java 开发者
Java 数据类型划分(整型类型)|学习笔记
快速学习 Java 数据类型划分(整型类型)
下一篇
无影云桌面