Как использовать Java для чтения из файла, который активно написанном?

голоса
83

У меня есть приложение, которое записывает информацию в файл. Эта информация используется пост-исполнение для определения годен / отказ / правильности применения. Я хотел бы быть в состоянии прочитать файл, который записываются так, что я могу сделать эту годно / отказ / корректность проверку в режиме реального времени.

Я полагаю, что это можно сделать, но каковы Гоча участвующие при использовании Java? Если чтение догоняет письма, он будет просто ждать, пока еще пишет вверх, пока файл не будет закрыт, или прочитанные сгенерирует исключение в этот момент? Если последнее, что мне делать тогда?

Моя интуиция в настоящее время толкает меня к BufferedStreams. Является ли это путь?

Задан 07/08/2008 в 00:57
источник пользователем
На других языках...                            


10 ответов

голоса
34

Не удалось получить пример работы с использованием , 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. Да я знаю, что в каменном веке по-прежнему.

Ответил 30/09/2008 в 20:32
источник пользователем

голоса
16

Посмотрите в использовании Tailer из Apache Commons IO. Он обрабатывает большинство краевых случаев.

Ответил 29/05/2012 в 17:28
источник пользователем

голоса
6

Если вы хотите, чтобы прочитать файл, пока он записывается и читать только новое содержание, то следующее поможет вам достичь того же.

Для запуска этой программы вы запустить его из командной строки / терминального окна и передать имя файла для чтения. Он будет читать файл, если вы не убьете программу.

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();
    }
}
Ответил 29/09/2015 в 19:08
источник пользователем

голоса
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);
        }
    }
}
Ответил 25/09/2015 в 13:45
источник пользователем

голоса
5

Вы также можете взглянуть на Java канал для блокировки часть файла.

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

Эта функция из FileChannelможет быть началом

lock(long position, long size, boolean shared) 

Вызов этого метода будет блокироваться, пока область не может быть заблокирована

Ответил 01/09/2008 в 17:31
источник пользователем

голоса
3

Ответ, кажется, «нет» ... и «да». Там, кажется, нет никакого реального способа знать, если файл открыт для записи другого приложения. Так, чтение из такого файла будет только прогрессировать, пока содержимое не будет исчерпано. Я принял совет Майка и написал несколько тестового кода:

Writer.java записывает строку в файл, а затем ждет пользователя нажать кнопку ввода, прежде чем писать еще одну строку в файл. Идея заключалась в том, что она может быть запущена, то читатель может быть запущена, чтобы увидеть, как он справляется с «частичным» файлом. Читатель написал в 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, конец документа может быть использован, чтобы сигнализировать это.

Ответил 07/08/2008 в 08:25
источник пользователем

голоса
1

Есть с открытым исходным кодом Java Графический Tail, который делает это.

https://stackoverflow.com/a/559146/1255493

public void run() {
    try {
        while (_running) {
            Thread.sleep(_updateInterval);
            long len = _file.length();
            if (len < _filePointer) {
                // Log must have been jibbled or deleted.
                this.appendMessage("Log file was reset. Restarting logging from start of file.");
                _filePointer = len;
            }
            else if (len > _filePointer) {
                // File must have had something added to it!
                RandomAccessFile raf = new RandomAccessFile(_file, "r");
                raf.seek(_filePointer);
                String line = null;
                while ((line = raf.readLine()) != null) {
                    this.appendLine(line);
                }
                _filePointer = raf.getFilePointer();
                raf.close();
            }
        }
    }
    catch (Exception e) {
        this.appendMessage("Fatal error reading log file, log tailing has stopped.");
    }
    // dispose();
}
Ответил 02/03/2015 в 20:04
источник пользователем

голоса
1

Не Java за се, но вы можете столкнуться с проблемами, где вы написали что-то в файл, но он не был на самом деле еще написано - это может быть в кэше где-нибудь, и чтение из одного файла не может реально дать вам новая информация.

Короткая версия - использование флеш () или любой другой соответствующий системный вызов, чтобы убедиться, что данные на самом деле записываются в файл.

Обратите внимание, я не говорю о кэше-памяти диска на уровне ОС - если ваши данные попадают сюда, он должен появиться в прочитанном () после этой точки. Может быть, что язык сам кэширует пишет, ожидая, пока буфер не заполнится или файл очищается / закрыто.

Ответил 07/08/2008 в 01:31
источник пользователем

голоса
0

Вы не можете прочитать файл, который открывается из другого процесса с использованием FileInputStream, FileReader или RandomAccessFile.

Но использование FileChannel непосредственно будет работать:

private static byte[] readSharedFile(File file) throws IOException {
    byte buffer[] = new byte[(int) file.length()];
    final FileChannel fc = FileChannel.open(file.toPath(), EnumSet.of(StandardOpenOption.READ));
    final ByteBuffer dst = ByteBuffer.wrap(buffer);
    fc.read(dst);
    fc.close();
    return buffer;
}
Ответил 03/01/2016 в 12:09
источник пользователем

голоса
0

Я никогда не пробовал, но вы должны написать тест, чтобы увидеть, если чтение из потока после того, как вы попали в конец будет работать, независимо от того, есть ли еще данные, записываемые в файл.

Есть ли причина, вы не можете использовать поток ввода / вывода по конвейеру? Записываются и читать данные из одного приложения (если да, то у вас есть данные, почему вам нужно прочитать из файла)?

В противном случае, может прочитать до конца файла, а затем следить за изменениями и стремиться туда, где вы остановились и продолжить ... хотя следить за условиями гонки.

Ответил 07/08/2008 в 01:37
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more