如何使用Java读取正在被主动写入的文件?

时间:2020-03-05 18:38:11  来源:igfitidea点击:

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

我认为可以做到这一点,但是使用Java时所涉及的陷阱是什么?如果阅读赶上了写作,它会只是等待更多的写操作直到文件关闭,还是此时读将引发异常?如果是后者,我该怎么办?

我的直觉目前将我推向BufferedStreams。这是要走的路吗?

解决方案

回答

不是Java本身,但是我们可能会遇到这样的问题,即我们已经向文件中写入了一些内容,但实际上尚未写入,但它可能位于某个地方的高速缓存中,并且从同一文件中读取内容实际上可能不会给我们带来好处。新讯息。

短版使用flush()或者任何相关的系统调用来确保数据实际上已写入文件中。

注意如果数据进入这里,我并不是在谈论操作系统级别的磁盘缓存,此后它应该出现在read()中。语言本身可能会缓存写操作,等待缓冲区填满或者刷新/关闭文件。

回答

我从未尝试过,但是我们应该编写一个测试用例,以查看在结束后从流中读取是否可以工作,而不管是否有更多数据写入该文件。

我们有理由不能使用管道输入/输出流吗?是否正在从同一应用程序中写入和读取数据(如果有,我们拥有数据,为什么需要从文件中读取数据)?

否则,可能要读到文件末尾,然后监视更改并寻找到上次停止的地方并继续...尽管要注意比赛条件。

回答

答案似乎是"否"和"是"。似乎没有真正的方法知道文件是否已打开以供其他应用程序写入。因此,从此类文件读取将一直进行到内容耗尽为止。我接受了Mike的建议,并编写了一些测试代码:

Writer.java将字符串写入文件,然后等待用户按下Enter键,然后再将另一行写入文件。其想法是可以启动它,然后可以开始阅读器以查看它如何处理"部分"文件。我写的读者在Reader.java中。

Writer.java

public class Writer extends Object
{
    Writer () {

    }

    public static String[] strings = 
        {
            "Hello World", 
            "Goodbye World"
        };

    public static void main(String[] args) 
        throws java.io.IOException {

        java.io.PrintWriter pw =
            new java.io.PrintWriter(new java.io.FileOutputStream("out.txt"), true);

        for(String s : strings) {
            pw.println(s);
            System.in.read();
        }

        pw.close();
    }
}

Reader.java

public class Reader extends Object
{
    Reader () {

    }

    public static void main(String[] args) 
        throws Exception {

        java.io.FileInputStream in = new java.io.FileInputStream("out.txt");

        java.nio.channels.FileChannel fc = in.getChannel();
        java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10);

        while(fc.read(bb) >= 0) {
            bb.flip();
            while(bb.hasRemaining()) {
                System.out.println((char)bb.get());
            }
            bb.clear();
        }

        System.exit(0);
    }
}

不能保证此代码是最佳实践。

这使Mike建议我们选择定期检查是否有新数据要从文件中读取的选项。然后,当确定读取已完成时,这需要用户干预以关闭文件读取器。或者,需要使读者知道文件的内容,并能够确定和结束写入条件。如果内容是XML,则可以使用文档末尾的信号。

回答

我们还可以查看用于锁定文件一部分的java通道。

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

FileChannel的此功能可能是一个开始

lock(long position, long size, boolean shared)

对该方法的调用将阻塞,直到可以锁定该区域为止

回答

无法使用示例使用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;
            }
        }
    }
}

当然,相同的东西可以用作计时器而不是线程,但是我将其留给程序员。我仍在寻找一种更好的方法,但这目前对我有效。

哦,我要警告一下:我正在使用1.4.2. 是的,我知道我还在石器时代。