Avatar billede stringbuffer Nybegynder
12. marts 2003 - 12:18 Der er 24 kommentarer og
1 løsning

Læse tekstif

Jeg vil gerne læse hele indholdet af en tekstfil ind i en string eller en stringbuffer.

Jeg har lavet noget lignende i C#, der kunne man:

StreamReader re = new StreamReader(filename, System.Text.Encoding.Default);
string data = re.ReadToEnd();
re.Close();


Jeg vil gerne gøre det samme i Java.
At læse enkelte linier dur ikke.
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 12:19 #1
Det skulle forresten have heddet "Læse tekstfil" i overskriften... stvaepfladde?
Avatar billede Slettet bruger
12. marts 2003 - 12:33 #2
Du kan vel gøre noget i retning af nedensående, men jeg har ikke testet.

FileInputSream fs = new FileInputStream("filename");
byte[] buffer = new buffer[fs.available()];
fs.read(buffer);
fs.close();
String file = new String(buffer);
Avatar billede Slettet bruger
12. marts 2003 - 12:35 #3
new String(buffer) bruger automatisk default charset
Avatar billede viht Nybegynder
12. marts 2003 - 12:35 #4
Det hurtigste er RandomAccessFile i java.io pakken:
File file = new File("C:/tekst.txt");
RandomAccessFile raf = new RandomAccessFile(file, "r");
if( raf.length() > Integer.MAX_VALUE )
  // Fil for stor         
byte[] result = new byte[ (int) raf.length() ];
raf.read( result );
raf.close();

String str = new String(result);
Avatar billede viht Nybegynder
12. marts 2003 - 12:37 #5
jjust >> available(...) på en stream returnerer ikke hvor meget der er i streamen, men hvor meget du på nuværende tidspunkt kan læse! Filen kan godt være væsentligt større jo.
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 12:40 #6
Er det ikke langsomt når der først læses ind i en byte[] og så skal det hele kopieres over i en string?
Avatar billede viht Nybegynder
12. marts 2003 - 12:42 #7
En String er jo essentielt bare et byte array med noget abstraktion ovenpå. Du er jo nødt til at kopiere indholdet over i strengen, når du ikke har pointere.
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 12:59 #8
ja, men en string bruger 2 bytes pr. tegn, det gør byte[] jo ikke.
Avatar billede viht Nybegynder
12. marts 2003 - 13:14 #9
Hvis du skal bruge filen meget kan du med nio mappe den direkte i memory og tilgå den derfra.

Med nedenstående test tager det lidt længere tid at læse filen ind i en streng hvis du bruger nio, men du kan til gengæld læse væsentligt hurtigere fra den når den endelig er inde.

// NioTest.java:
import java.nio.*;
import java.nio.channels.*;
import java.io.*;

public class NioTest {
    public static void main(String[] args) {
        try {
            File file = new File("C:/tekst.txt");

            long start = System.currentTimeMillis();
            FileChannel rwChannel = new RandomAccessFile(file, "rw").getChannel();
          ByteBuffer wrBuf = rwChannel.map(FileChannel.MapMode.READ_WRITE, 0, (int)rwChannel.size());
         
          StringBuffer buffer = new StringBuffer();
          for( int i = 0; i < wrBuf.capacity(); i++ ) {
              buffer.append((char)wrBuf.get());
          }
          String str = buffer.toString();
          System.out.println ("TIME nio: " +(System.currentTimeMillis()-start));

          /*
          long start = System.currentTimeMillis();
          RandomAccessFile rw = new RandomAccessFile(file, "rw");
          byte[] result = new byte[(int)rw.length()];
          rw.read(result);
          String str = new String(result);
          System.out.println ("TIME old " +(System.currentTimeMillis()-start));
          */
        }
        catch( FileNotFoundException fnfe ) {
            fnfe.printStackTrace();
        }
        catch( IOException ioe ) {
            ioe.printStackTrace();
        }
  }
}
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 15:11 #10
Bliver filen så cached i hukommelsen så den anden gang, man kører programmet, er filen allerede mapped fra sidste gang?
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 15:12 #11
Eller hvor er det lige at man vinder i performance?
Avatar billede viht Nybegynder
12. marts 2003 - 15:47 #12
Intet bør være tilovers når et program afsluttes. Filen er kun cached sålænge programmet kører.
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 15:51 #13
Dit eksempel med memmapping tog 31 ms at køre, hvorimod dit eksempel med at læse ind i en byte[] tog under 1 ms.

Tak fordi du lavede disse eksempler, det er i hvert fald noget, jeg kan arbejde ud fra :)
Avatar billede viht Nybegynder
12. marts 2003 - 15:58 #14
Tak for point, og held og lykke.
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 16:04 #15
Selv tak :)

Har en gang kunnet lidt Java, men dengang hed det vist Java 1.0 *G*
Men jeg har jo lavet noget kode i C#, og jeg er ret sikker på at det (bortset fra fil-operationer) forholdsvis let kan oversættes til Java.
Avatar billede Slettet bruger
12. marts 2003 - 17:31 #16
viht >> Du har ret mht. available.

Har du et godt argument for at RandomAccessFile er hurtigere end at bruge en FileInputStream? Jeg har prøvet med nedenstående program, og får væsentlige bedre tider for FileInputStream.

import java.io.*;

public class filetest {
    public static void main(String[] args) {
    try {
        long start = System.currentTimeMillis();
        File f = new File("color.txt");
        byte[] buffer = new byte[(int) f.length()];
        FileInputStream fis = new FileInputStream(f);
        fis.read(buffer);
        String str = new String(buffer);
        long end = System.currentTimeMillis();
        fis.close();
        System.out.println(end-start);
    } catch(Exception e) {
        e.printStackTrace();
    }
   
    try {
        long start = System.currentTimeMillis();
        RandomAccessFile raf = new RandomAccessFile("color.txt", "r");
        byte[] buffer = new byte[(int) raf.length()];
        raf.readFully(buffer);
        String str = new String(buffer);
        long end = System.currentTimeMillis();
        raf.close();
        System.out.println(end-start);
    } catch(Exception e) {
        e.printStackTrace();
    }
    }
}
Avatar billede viht Nybegynder
12. marts 2003 - 18:01 #17
Det er pudsigt du gør det.. jeg testede det for noget tid siden, og der var RAF klart foran :) Det var også mest på linux jeg testede der.
Avatar billede Slettet bruger
12. marts 2003 - 18:17 #18
Jeg har kun testet under XP, men tager på kontoret senere i aften, så det kan være jeg lige tester på linux for sjov :)
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 18:21 #19
Heh, var lidt nysgerrig mht. hvem af jer har ret, så jeg lavede flg. test:

import java.io.*;

public class filetest {
    public static void main(String[] args) {
    try {
        long start = System.currentTimeMillis();
   
    for (int i=0; i<100; i++)
    {
            File f = new File("C:/bigfile.html");
            byte[] buffer = new byte[(int) f.length()];
            FileInputStream fis = new FileInputStream(f);
            fis.read(buffer);
            fis.close();
            String str = new String(buffer);
    }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    } catch(Exception e) {
        e.printStackTrace();
    }
   
    try {
        long start = System.currentTimeMillis();
    for (int i=0; i<100; i++)
    {
            RandomAccessFile raf = new RandomAccessFile("C:/bigfile.html", "r");
            byte[] buffer = new byte[(int) raf.length()];
            raf.readFully(buffer);
            raf.close();
            String str = new String(buffer);
    }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    } catch(Exception e) {
        e.printStackTrace();
    }
    }
}

Filen, der blev brugt til testen, var godt 78 kB stor.
Resultatet blev:
796
672
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 18:21 #20
Så RandomAccessFile er hurtigere, men ikke vildt meget hurtigere.
Avatar billede Slettet bruger
12. marts 2003 - 18:32 #21
Har du prøvet bare at køre programmet som jeg skrev? Altså uden for-løkker!

Jeg prøvede lige igen, på en 400 kb stor fil, og der var FIS dobbelt så hurtig som RAF, men da jeg prøvede med for-løkker var RAF hurtigst.

??
Avatar billede Slettet bruger
12. marts 2003 - 18:35 #22
Gad vide om javac kan optimere et eller andet væk?
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 20:06 #23
Det kommer vel også an på om du timer det hele, eller kun efter at filen er åbnet.
Avatar billede stringbuffer Nybegynder
12. marts 2003 - 20:07 #24
da jeg timede det hele uden at køre det i en løkke, fik jeg ca. 31 ms med FIS og 16 ms med RAF.
Avatar billede Slettet bruger
12. marts 2003 - 21:02 #25
Jeg brugte det program jeg skrev her! Ser lige på det senere igen. Det lyder lidt spøjst!
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester