Vra

Ek het 'n program wat inligting na 'n lêer skryf. Hierdie inligting word gebruik post-uitvoering te slaag / mislukking / korrektheid van die aansoek te bepaal. Ek wil graag in staat wees om die lêer te lees soos dit geskryf sodat ek hierdie pass / mislukking / korrektheid tjeks kan doen in real time.

Ek neem aan dit is moontlik om dit te doen, maar wat is die Gotcha se betrokke by die gebruik van Java? As die lesing inhaal tot die skryf, sal dit net wag vir meer skryf tot die lêer gesluit word, of sal die lees gooi 'n uitsondering op hierdie punt? As die laaste, wat moet ek doen dan?

My intuïsie is tans besig om my teenoor BufferedStreams. Is dit die pad om te gaan?

Was dit nuttig?

Oplossing

Kan die voorbeeld nie kry om te werk met behulp van FileChannel.read(ByteBuffer), want dit is nie 'n blok lees. Het egter kry onder die kode te werk:

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;
            }
        }
    }
}

Natuurlik dieselfde ding sal werk as 'n timer in plaas van 'n draad, maar ek laat dit aan die programmeerder. Ek is nog steeds op soek na 'n beter manier, maar dit werk vir my vir nou.

O ja, en ek sal dit caveat met: Ek gebruik 1.4.2. Ja ek weet ek is in die klip ouderdomme nog.

Ander wenke

As jy wil 'n lêer te lees terwyl dit geskryf en lees net die nuwe inhoud dan volgende sal jou help om dieselfde te bereik.

Om hierdie program sal jy dit uit command prompt / terminale venster van stapel te stuur hardloop en slaag die lêernaam te lees. Dit sal die lêer lees nie, tensy jy die program dood te maak.

java FileReader c: \ myfile.txt

As jy tik 'n reël van die teks, behalwe dit uit notepad en jy sal die teks gedruk in die konsole te sien.

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();
    }
}

Jy kan ook 'n blik op Java kanaal vir locking 'n deel van 'n lêer.

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

Hierdie funksie van die FileChannel dalk 'n begin wees

lock(long position, long size, boolean shared) 

'n aanroeping van hierdie metode sal blok totdat die streek gesluit kan word

Ek is dit heeltemal eens met Josua se reaksie , Training is geskik vir die werk in hierdie situasie. Hier is 'n voorbeeld:

Dit skryf 'n lyn elke 150 ms in 'n lêer, terwyl die lees van hierdie einste lêer elke 2500 Me

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);
        }
    }
}

Die antwoord blyk te wees "nee" ... en "ja". Dit blyk dat daar geen werklike manier om te weet of 'n lêer is oop vir die skryf van 'n ander program wees. So, lees van so 'n lêer sal net vorder tot inhoud is uitgeput. Ek het raad Mike se en skryf 'n paar toets-kode:

Writer.java skryf 'n string na 'n lêer en dan wag vir die gebruiker om druk enter voor te skryf 'n ander lyn in te dien. Die idee is dat dit kan begin word, dan 'n leser kan begin om te sien hoe dit is middels met die "gedeeltelike" lêer. Die leser het ek geskryf is in 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);
    }
}

Geen waarborg dat hierdie kode is die beste praktyk.

Dit laat die opsie voorgestel deur Mike van tyd tot tyd nagaan indien daar nuwe data te lees van die lêer. Dit vereis dan gebruiker intervensie om die lêer leser sluit wanneer dit word bepaal dat die lesing is voltooi. Of, moet die leser bewus gemaak moet word van die inhoud van die lêer en in staat wees om vas te stel en einde van skryf toestand. As die inhoud was XML, kon die einde van dokument gebruik word om hierdie sein.

Nie Java per-se, maar jy kan loop in kwessies waar jy iets geskryf het om 'n lêer, maar dit is nog nie eintlik nog geskryf - dit kan wees in 'n kas êrens, en lees uit dieselfde lêer kan nie eintlik gee jou die nuwe inligting.

Kort weergawe -. Die gebruik spoel () of wat ook al die betrokke stelsel oproep is om te verseker dat jou data eintlik geskryf is om die lêer

Let ek praat nie van die bedryfstelsel vlak skyf kas - as jou data kry in hier, moet dit in 'n lees () na hierdie punt verskyn. Dit mag wees dat die taal self caches skryf, wag totdat 'n buffer vul of lêer uitgespoel / gesluit.

Daar is 'n Open Source Java Graphic stert wat dit doen.

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();
}

Ek het nog nooit probeer om dit, maar moet jy 'n toetssaak skryf om te sien of lees van 'n stroom nadat jy druk op die einde sal werk, ongeag of daar meer data geskryf om die lêer.

Is daar 'n rede waarom jy kan 'n lopende toevoer / afvoer stroom nie gebruik? Word die data geskryf en lees uit dieselfde aansoek (indien wel, jy die data het, hoekom doen wat jy nodig het om te lees van die lêer)?

Andersins, miskien lees tot die einde van lêer, dan monitor vir veranderinge en soek na waar jy opgehou het en voortgaan ... al kyk uit vir ras voorwaardes.

Jy kan 'n lêer wat oopgemaak van 'n ander proses met behulp van FileInputStream, FileReader of RandomAccessFile nie lees nie.

Maar met behulp van FileChannel sal direk werk:

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;
}
Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top