source

Java를 사용하여 활성 쓰기 대상 파일에서 읽으려면 어떻게 해야 합니까?

gigabyte 2022. 9. 15. 22:53
반응형

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

반응형