如何使用Java从正在写入的文件中读取?

Ant*_*amp 96 java file-io file

我有一个将信息写入文件的应用程序.在执行后使用此信息来确定应用程序的通过/失败/正确性.我希望能够在写入文件时读取该文件,以便我可以实时进行这些通过/失败/正确性检查.

我认为可以这样做,但使用Java时涉及到的问题是什么?如果读取符合写入,它是否会等待更多写入直到文件关闭,或者此时读取是否会抛出异常?如果是后者,我该怎么办?

我的直觉目前正在推动我走向BufferedStreams.这是要走的路吗?

Jos*_*don 35

无法使用该示例,FileChannel.read(ByteBuffer)因为它不是阻塞读取.但是,让下面的代码工作:

boolean running = true;
BufferedInputStream reader = new BufferedInputStream(new FileInputStream( "out.txt" ) );

public void run() {
    while( running ) {
        if( reader.available() > 0 ) {
            System.out.print( (char)reader.read() );
        }
        else {
            try {
                sleep( 500 );
            }
            catch( InterruptedException ex ) {
                running = false;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当然同样的事情可以作为计时器而不是线程,但我把它留给程序员.我还在寻找一种更好的方法,但这对我来说现在很有用.

哦,我会注意到这一点:我正在使用1.4.2.是的我知道我还在石器时代.


小智 8

如果您想在写入文件时读取文件并且只读取新内容,则以下内容将帮助您实现相同的目标.

要运行此程序,您将从命令提示符/终端窗口启动它并传递文件名以进行读取.除非你杀了程序,否则它会读取文件.

java FileReader c:\ myfile.txt

当您键入一行文本时,将其从记事本中保存,您将看到控制台中打印的文本.

public class FileReader {

    public static void main(String args[]) throws Exception {
        if(args.length>0){
            File file = new File(args[0]);
            System.out.println(file.getAbsolutePath());
            if(file.exists() && file.canRead()){
                long fileLength = file.length();
                readFile(file,0L);
                while(true){

                    if(fileLength<file.length()){
                        readFile(file,fileLength);
                        fileLength=file.length();
                    }
                }
            }
        }else{
            System.out.println("no file to read");
        }
    }

    public static void readFile(File file,Long fileLength) throws IOException {
        String line = null;

        BufferedReader in = new BufferedReader(new java.io.FileReader(file));
        in.skip(fileLength);
        while((line = in.readLine()) != null)
        {
            System.out.println(line);
        }
        in.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在读取文件的时间和文件长度的时间之间,外部进程可能会向文件中添加更多数据.如果是这样,这将导致读取过程丢失写入文件的数据. (2认同)
  • 此代码消耗大量 CPU,因为循环中没有 thread.sleep 调用。如果不添加少量延迟,此代码往往会使 CPU 非常繁忙。 (2认同)

Fre*_*rin 5

您还可以查看java通道来锁定文件的一部分.

http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html

这个功能FileChannel可能是一个开始

lock(long position, long size, boolean shared) 
Run Code Online (Sandbox Code Playgroud)

调用此方法将阻塞,直到可以锁定该区域


ToY*_*nos 5

我完全同意约书亚的回应,Tailer在这种情况下适合这份工作.这是一个例子:

它在文件中每150毫秒写一行,同时每2500毫秒读取一个相同的文件

public class TailerTest
{
    public static void main(String[] args)
    {
        File f = new File("/tmp/test.txt");
        MyListener listener = new MyListener();
        Tailer.create(f, listener, 2500);

        try
        {
            FileOutputStream fos = new FileOutputStream(f);
            int i = 0;
            while (i < 200)
            {
                fos.write(("test" + ++i + "\n").getBytes());
                Thread.sleep(150);
            }
            fos.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private static class MyListener extends TailerListenerAdapter
    {
        @Override
        public void handle(String line)
        {
            System.out.println(line);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @StealthRabbi然后最好的办法是搜索正确的链接,并用它编辑答案。 (2认同)