Java를 사용하여 활성 쓰기 대상 파일에서 읽으려면 어떻게 해야 합니까?
나는 파일에 정보를 쓰는 어플리케이션을 가지고 있다.이 정보는 응용 프로그램의 합격/실패/정확성을 판단하기 위해 실행 후 사용됩니다.실시간으로 이러한 패스/실패/정확성 체크를 할 수 있도록 작성 중인 파일을 읽을 수 있도록 하고 싶습니다.
가능한 일이라고 생각합니다만, Java를 사용할 때 gotcha는 어떤 관계가 있습니까?판독치가 기입을 따라잡으면 파일이 닫힐 때까지 더 많은 쓰기를 기다립니다.아니면 이 시점에서 판독치가 예외를 발생시킬까요?후자의 경우 어떻게 해야 합니까?
내 직감은 현재 나를 Buffered Streams로 몰아넣고 있다.이렇게 가는 거야?
할 수 .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를 사용하고 있습니다.네, 제가 아직 석기시대라는 걸 알아요.
작성 중에 파일을 읽고 새로운 내용만 읽으려면 다음 절차를 따릅니다.
이 프로그램을 실행하려면 명령 프롬프트/터미널 창에서 프로그램을 실행하고 파일 이름을 전달합니다.프로그램을 종료하지 않는 한 파일을 읽습니다.
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();
}
}
파일의 일부를 잠그기 위해 Java 채널을 살펴볼 수도 있습니다.
http://java.sun.com/javase/6/docs/api/java/nio/channels/FileChannel.html
는 " " " " " "FileChannel
있다
lock(long position, long size, boolean shared)
이 메서드를 호출하면 영역을 잠글 수 있을 때까지 차단됩니다.
저는 조슈아의 답변에 전적으로 동의합니다. 테일러는 이 상황에서 이 일에 적임입니다.다음은 예를 제시하겠습니다.
파일에 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);
}
}
}
대답은 '아니오'와 '그렇다'인 것 같다.파일이 다른 응용 프로그램에서 쓰기 위해 열려 있는지 여부를 알 수 있는 실질적인 방법은 없는 것 같습니다.따라서 이러한 파일의 읽기는 콘텐츠가 소진될 때까지 계속 진행됩니다.마이크의 조언을 받아 테스트 코드를 작성했습니다.
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 그래픽테일이 있습니다.
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();
}
FileInputStream, FileReader 또는 RandomAccessFile을 사용하여 다른 프로세스에서 열린 파일을 읽을 수 없습니다.
그러나 File Channel을 직접 사용하면 다음과 같이 동작합니다.
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;
}
Java 자체는 아니지만 파일에 실제로 쓰지 않은 문제가 발생할 수 있습니다. - 캐시에 저장되어 있을 수 있습니다.또, 같은 파일로부터 읽어내도, 실제로 새로운 정보를 얻을 수 없는 경우도 있습니다.
쇼트 버전 - flush() 또는 관련된 시스템 호출을 사용하여 데이터가 파일에 실제로 기록되도록 합니다.
OS 레벨의 디스크 캐시를 말하는 것이 아닙니다.데이터가 여기에 들어가면 이 시점 이후에 read()에 표시됩니다.언어 자체가 쓰기를 캐시하고 버퍼가 가득 찰 때까지 기다리거나 파일이 플러시/닫힐 수 있습니다.
시도해 본 적은 없지만, 파일에 데이터가 더 많이 쓰여져 있는지 여부에 관계없이 끝부분을 누른 후 스트림에서 읽어낼 수 있는지 테스트 케이스를 작성해야 합니다.
파이프로 연결된 입출력 스트림을 사용할 수 없는 이유가 있습니까?같은 애플리케이션에서 데이터를 쓰고 읽습니까(읽을 경우 데이터를 가지고 있는데 왜 파일에서 읽어야 합니까)?
그렇지 않으면 파일이 끝날 때까지 읽은 다음 변경 사항을 모니터링하고 중단한 위치로 이동하여 계속 진행합니다.하지만 레이스 상황을 조심하라.
언급URL : https://stackoverflow.com/questions/4149/how-do-i-use-java-to-read-from-a-file-that-is-actively-being-written-to
'source' 카테고리의 다른 글
MySQL에서 MariaDB로 또는 그 반대로 이행 (0) | 2022.09.15 |
---|---|
어떻게 사용자 입력을 명령줄 인수를 읽고자. (0) | 2022.09.15 |
C/C++의 작은따옴표, 큰따옴표 및 크기('a') (0) | 2022.09.15 |
codeigniter 4 mysql 쿼리 고유 또는 그룹별 (0) | 2022.09.15 |
처음 사용한 후 재할당 시 로컬 변수의 UnboundLocalError (0) | 2022.09.15 |