Onko mitään tapaa seurata sitä, kuinka paljon tekstitiedostoon on kertynyt "tavaraa" ohjelman suorituksen aikana, kun tekstitiedosto on auki kirjoittamista varten? Kirjoitan käyttäen PrintWriter-luokkaa.
Sijainnin tiedostossa saa FileOutputStream-luokan kautta FileChannel-luokan position-metodilla. Kyseinen virta täytyy siis ottaa talteen jo tiedoston avaamisen yhteydessä, koska PrintWriterista sitä ei enää saa kaivettua. Palautuva luku voi erota PrintWriterille annetusta määrästä puskuroinnin vuoksi, ellei ensin kutsuta flush-metodia. Lisäksi pitää huomioida tiedostossa jo olevat tiedot, jos tiedosto avataan lisäystä varten (append-tilassa).
import java.io.*; class tmp { public static void main(String[] args) throws Exception { File f = new File("tmp.txt"); FileOutputStream s = new FileOutputStream(f); PrintWriter w = new PrintWriter(s); System.out.println("alku: " + s.getChannel().position()); // 0 w.print("Moikka!\n"); System.out.println("print: " + s.getChannel().position()); // 0 w.flush(); System.out.println("flush: " + s.getChannel().position()); // 8 } }
Saattaisinpa itse vain kirjoittaa proxy- / decorator-luokan, joka ottaa talteen kirjoitettavan datan määrän ennen kuin syöttää sen varsinaiselle PrintWriterille. Kai tuollainen nyt javassakin on mahdollista.
Pseudona suurin piirtein näin:
File file = new File("tmp.txt"); FileOutputStream stream = new FileOutputStream(file); MyWriter writer = new MyWriter(new PrintWriter(stream)); writer.print("lallallaa"); writer.print("lalalalalaa"); // Oma metodi int bytes_written = writer.getBytesWritten();
Edit: Tosin tuon PrintWriterin rajapinta näyttää niin laajalta, että varmaan aika työlästä olisi tehdä noin.
The Alchemist kirjoitti:
Saattaisinpa itse vain kirjoittaa proxy- / decorator-luokan, joka ottaa talteen kirjoitettavan datan määrän ennen kuin syöttää sen varsinaiselle PrintWriterille.
Eihän tuo tapa toimi järkevästi. Pitäisi huomioida kaikki noin 20 metodia, joilla PrintWriterillä voi tulostaa. Pitäisi muuntaa itse tiedot tekstiksi ja käsitellä formatoinnit ("%d" jne.), mikä käytännössä kumoaa PrintWriterin hyödyt. Pitäisi huomioida myös tiedoston merkistö, jos haluaa laskea tavuja eikä merkkejä.
Jos jokin oma luokka kiinnostaa, fiksumpaa on tehdä PrintWriterin perivä luokka, joka kuitenkin säilyttää FileOutputStream-olion ja käyttää edellä ehdottamiani metodeita tavumäärän hakemiseen. Näin pystyy myös välittämään olion PrintWriter-tyyppisenä parametrina ohjelman muille funktioille, jolloin koodin muut muutokset pysyvät melko minimaalisina.
class MyWriter extends PrintWriter { FileOutputStream stream; public MyWriter(FileOutputStream stream) { this.stream = stream; super(stream); } public long position() { // FIXME: flush()? // FIXME: return ...position() - this.positionWhenCreated? return stream.getChannel().position(); } }
Aihe on jo aika vanha, joten et voi enää vastata siihen.