Mam aplikację, która zapisuje informacje do pliku. Informacje te są wykorzystywane po wykonaniu do określenia wyniku / niepowodzenia / poprawności aplikacji. Chciałbym móc odczytać plik w trakcie jego zapisywania, aby móc przeprowadzać kontrole zaliczenia / niepowodzenia / poprawności w czasie rzeczywistym.
Zakładam, że jest to możliwe, ale jakie są problemy związane z używaniem Javy? Jeśli odczyt dogoni zapis, czy będzie po prostu czekał na kolejne zapisy, aż plik zostanie zamknięty, czy też odczyt zgłosi wyjątek w tym momencie? Jeśli to drugie, co mam wtedy zrobić?
Moja intuicja popycha mnie obecnie w stronę BufferedStreams. Czy to jest droga?
Odpowiedzi:
Nie można uruchomić przykładu,
FileChannel.read(ByteBuffer)
ponieważ nie jest to odczyt blokujący. Czy jednak kod poniżej działał:Oczywiście to samo działałoby jako licznik czasu zamiast wątku, ale zostawiam to programiście. Wciąż szukam lepszego sposobu, ale na razie to działa.
Aha, i zastrzegam to: używam 1.4.2. Tak, wiem, że wciąż jestem w epoce kamienia.
źródło
Jeśli chcesz czytać plik w trakcie jego zapisywania i czytać tylko nową zawartość, to poniższe pomoże Ci to osiągnąć.
Aby uruchomić ten program, uruchomisz go z wiersza poleceń / okna terminala i przekażesz nazwę pliku do odczytania. Odczyta plik, chyba że zabijesz program.
java FileReader c: \ myfile.txt
Podczas wpisywania linii tekstu zapisz ją z notatnika, a zobaczysz tekst wydrukowany w konsoli.
źródło
BufferedReader
tworzenie w każdym wywołaniu pętli jest bezcelowe. Gdyby był tworzony raz, pomijanie nie byłoby konieczne, ponieważ buforowany czytelnik czyta nowe wiersze, gdy tylko się pojawią.Możesz również rzucić okiem na kanał java do blokowania części pliku.
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html
Ta funkcja
FileChannel
może być początkiemWywołanie tej metody będzie blokowane do momentu zablokowania regionu
źródło
Całkowicie zgadzam się z odpowiedzią Joshuy , Tailer nadaje się do pracy w tej sytuacji. Oto przykład :
Zapisuje linię co 150 ms w pliku, podczas gdy ten sam plik odczytuje co 2500 ms
źródło
Wydaje się, że odpowiedź brzmi „nie”… i „tak”. Wydaje się, że nie ma prawdziwego sposobu sprawdzenia, czy plik jest otwarty do zapisu w innej aplikacji. Tak więc czytanie z takiego pliku będzie kontynuowane do wyczerpania zawartości. Posłuchałem rady Mike'a i napisałem kod testowy:
Writer.java zapisuje ciąg do pliku, a następnie czeka, aż użytkownik naciśnie klawisz Enter, zanim zapisze kolejną linię do pliku. Chodzi o to, że można go uruchomić, a następnie czytelnik może zacząć zobaczyć, jak radzi sobie z plikiem „częściowym”. Czytelnik, którego napisałem, znajduje się w Reader.java.
Writer.java
Reader.java
Nie ma gwarancji, że ten kod jest najlepszymi praktykami.
Pozostawia to sugerowaną przez Mike'a opcję okresowego sprawdzania, czy z pliku są nowe dane do odczytania. Następnie wymaga to interwencji użytkownika w celu zamknięcia czytnika plików, gdy zostanie ustalone, że odczyt jest zakończony. Lub czytelnik musi być świadomy zawartości pliku i być w stanie określić i zakończyć zapis. Gdyby treść była w formacie XML, można by to zasygnalizować na końcu dokumentu.
źródło
Nie Java jako taka, ale możesz napotkać problemy, w których zapisałeś coś do pliku, ale tak naprawdę nie został jeszcze zapisany - może znajdować się gdzieś w pamięci podręcznej, a odczyt z tego samego pliku może w rzeczywistości nie dać nowe informacje.
Wersja skrócona - użyj flush () lub innego odpowiedniego wywołania systemowego, aby upewnić się, że dane są faktycznie zapisywane w pliku.
Uwaga Nie mówię o pamięci podręcznej dysku na poziomie systemu operacyjnego - jeśli twoje dane dostaną się tutaj, powinny pojawić się w read () po tym momencie. Może się zdarzyć, że sam język buforuje zapisy, czekając, aż bufor się zapełni lub plik zostanie opróżniony / zamknięty.
źródło
Istnieje Open Source Java Graphic Tail, który to robi.
https://stackoverflow.com/a/559146/1255493
źródło
Nie można odczytać pliku, który jest otwierany z innego procesu za pomocą FileInputStream, FileReader lub RandomAccessFile.
Ale bezpośrednie użycie FileChannel zadziała:
źródło
Nigdy tego nie próbowałem, ale powinieneś napisać przypadek testowy, aby sprawdzić, czy czytanie ze strumienia po osiągnięciu końca będzie działać, niezależnie od tego, czy w pliku jest więcej danych.
Czy jest jakiś powód, dla którego nie możesz używać potokowego strumienia wejścia / wyjścia? Czy dane są zapisywane i odczytywane z tej samej aplikacji (jeśli tak, masz dane, po co czytać z pliku)?
W przeciwnym razie może czytać do końca pliku, a następnie monitorować zmiany i szukać miejsca, w którym skończyłeś, i kontynuować ... ale uważaj na warunki wyścigu.
źródło