【问题标题】:Read to the end of file in java在java中读到文件末尾
【发布时间】:2014-04-25 08:58:57
【问题描述】:

我确实通过 Java 读取 Linux 中的串行接口文件。有时我只需要丢弃所有数据,只读取新数据。

解释:有大量数据并且新数据即将到来,所以我必须丢弃现有缓冲区并开始等待新数据。外部板只是不断发送。我最终读取了旧数据,只是在几次迭代中我就有了当前值。我只需要跳到结束并等待新数据集,而不是阅读所有旧废话。

String file = "/dev/ttyO1";
FileInputStream inputStream  = new FileInputStream(file);

private static byte[] readUntil(InputStream in, int timeout) throws IOException {
//        long lastTime = System.currentTimeMillis();
    while (true) {
        if (in.available() > 0) {
            if (in.read() == 83)
                break;
        }
        try { Thread.sleep(20); } catch (Exception e) {}
    }
    byte[] text = new byte[10];
    for (int i = 0; i < 10; i++) {
        text[i] = (byte) in.read();
        if (text[i]=="E".getBytes()[0]) break;
        try { Thread.sleep(20); } catch (Exception e) {}
    }
    in.read(); // just read last one
    return text;
}

我只是不知道如何丢弃现有数据并只读新数据。

【问题讨论】:

  • 您究竟需要什么帮助?我不明白。
  • Thread.sleep(20)的目的是什么??
  • Thread.sleep(20) - 我的本意是为了节省处理器功率...我可能错了...
  • 我不明白这个问题。尽可能快地读取所有数据。当数据不可用时,读取将阻塞。因此,可用/睡眠循环是没有意义的。我不明白你的问题是什么。

标签: java java-io


【解决方案1】:

我假设您真正想要的是刷新串行端口传入缓冲区中的所有数据。

在 Linux 上,在 C 程序中,you would be able to do

tcflush(fd, TCIFLUSH)

刷新传入的缓冲区。但是您无法直接从 Java 中执行此操作 - 它不是独立于平台的功能。

您可以编写一个小型 C 程序来执行此操作,然后将数据从 /dev/ttyO1 管道传输到标准输出。您可以使用 ProcessBuilder 从您的 Java 代码启动该程序并读取其数据,而不是直接读取串行端口。


再想一想,你不需要 C 程序做任何管道,你只需要调用它一次,然后你就可以从 Java 中打开/dev/tty01

这是一个可以执行此操作的小型 C 程序:

#include <sys/types.h> 
#include <sys/stat.h> 
#include <termios.h>
#include <fcntl.h> 
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char** argv) {
    int i;
    for (i = 1; i < argc; i++) {
        int fd = open(argv[i], O_NOCTTY, O_RDONLY);
        if (fd >= 0) {
            int result = tcflush(fd, TCIFLUSH);
            close(fd);
            if (result == -1) {
                fprintf(stderr, "%s: Couldn't open file %s; %s\n",
                        argv[0], argv[i], strerror(errno));
                exit (EXIT_FAILURE);
            }
        } else {
            fprintf(stderr, "%s: Couldn't open file %s; %s\n",
                    argv[0], argv[i], strerror(errno));
            exit (EXIT_FAILURE);
        }
    }
}

使用gcc -o tcflush tcflush.c 编译并使用tcflush /dev/tty01 运行。

【讨论】:

  • 我认为不仅可以使用外部程序,还可以使用 JNI,它仍然依赖于平台,但没有额外的过程。
  • @AlexanderKudrevatykh 是的。如果性能非常重要,OP 应该考虑 JNI。但如果这符合他的要求,最好先使用外部程序进行检查(例如,在刷新缓冲区和读取数据之间可能存在时间问题)
【解决方案2】:

我不知道“Linux 中的串行接口文件”到底是什么。但我认为它是一个简单的文件,它一直附加一些文本,你想等待附加的新内容,而不是从头开始读取整个文件。您可以使用RandomAccessFile 类的seek(long) 方法来跳过数据。或者您可以在到达文件末尾时睡一会儿。

public static void main(String[] args) throws Exception {
    FileInputStream fis = new FileInputStream("src/file.txt");
    int i = 0;
    while (i < 50) { // read only 50 bytes
        byte b = (byte)fis.read();

        if (b == -1) { // end of file, wait
            Thread.sleep(500L);
            continue;
        }
        System.out.print((char) b);
        i++;
    }
    fis.close();
}

这只是一个简单的例子。我最多只能读取 50 个字节,但您想读取的内容远不止这些。也许你可以使用超时。

【讨论】:

    【解决方案3】:

    外接板一直在发送。

    这看起来更像是事件驱动方法的目标,而不是通常的顺序读取。

    您是否考虑过使用RXTXjSSC? 您可以在 Arduino IDE 源代码中找到示例:SerialMonitorSerial

    【讨论】:

      【解决方案4】:

      从代码中您的目标非常不清楚。我想你想要一些功能,比如 linux 中的 tail 命令。如果是这样,下面的代码很有帮助..请运行它并检查它..

      import java.io.*;
      
      public class FileCheck {
      
          static long sleepTime = 1000 * 1;
          static String file_path = "/dev/ttyO1";
      
          public static void main(String[] args) throws IOException {
                  BufferedReader input = new BufferedReader(new FileReader(file_path));
                  String currentLine = null;
                  while (true) {
                      if ((currentLine = input.readLine()) != null) {
                          System.out.println(currentLine);
                          continue;
                      }
                      try {
                          Thread.sleep(sleepTime);
                      } catch (InterruptedException e) {
                          Thread.currentThread().interrupt();
                          break;
                      }
                  }
                  input.close();
          }
      }
      

      【讨论】:

      • 它读取文件,当你添加包含时,它会在控制台上显示新的常量。现在,你想达到什么目标?
      • readLine() 方法在流结束时返回 null。此时,对端已经关闭了连接,所以再也不会有数据了。因此,睡眠并再次尝试 readLine() 是没有意义的。 -1
      • 亲爱的,请运行该程序以了解睡眠的重要性。它会在内部...之后chk文件以获取数据。
      • 你能告诉我上面的代码会出现什么问题吗?仅供参考。
      • 睡眠的重要性为零,无论是“亲爱的”还是其他。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      • 2011-08-19
      相关资源
      最近更新 更多