2013-02-26 11 views
5

Chcę odczytać wiersz pliku po wierszu. BufferedReader jest znacznie szybszy niż RandomAccessFile lub BufferedInputStream. Ale problem polega na tym, że nie wiem, ile bajtów przeczytałem. Skąd wiadomo, że bajty są przeczytane (przesunięcie)? Próbowałem.Jak poznać bajty odczytu (przesunięcie) BufferedReader?

String buffer; 
int offset = 0; 

while ((buffer = br.readLine()) != null) 
    offset += buffer.getBytes().length + 1; // 1 is for line separator 

Działa, jeśli plik jest mały. Jednak, gdy plik staje się duży, przesunięcie staje się mniejsze niż wartość rzeczywista. Jak mogę uzyskać offset?

+0

Jakie większe zadanie próbujesz osiągnąć? Zasadniczo jest to trudne ze względu na wewnętrzny bufor (i kodowanie oraz różne zakończenia linii). –

+0

Chcę uzyskać przesunięcia początku linii. Używam tego offsetu do odczytu części pliku za pomocą RandomAccessFile później. – user1301568

+0

Zakładasz, że istnieje tylko jeden bajt separatora linii, np. \ n. Czy możesz to założyć? – EJP

Odpowiedz

-3

Jeśli chcesz odczytać pliku linia po linii, polecam ten kod:

import java.io.*; 
class FileRead 
{ 
public static void main(String args[]) 
    { 
    try{ 
    // Open the file that is the first 
    // command line parameter 
    FileInputStream fstream = new FileInputStream("textfile.txt"); 
    // Use DataInputStream to read binary NOT text. 
    BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); 
    String strLine; 
    //Read File Line By Line 
    while ((strLine = br.readLine()) != null) { 
    // Print the content on the console 
    System.out.println (strLine); 
    } 
    //Close the input stream 
    in.close(); 
    }catch (Exception e){//Catch exception if any 
    System.err.println("Error: " + e.getMessage()); 
    } 
    } 
} 

zawsze używać tej metody w przeszłości, i działa świetnie!

Źródło: Here

+2

Twoja odpowiedź jest trochę zła, ponieważ powinieneś zamknąć zewnętrzne zasoby w bloku finally, również nie odpowiadasz na pytanie, a poza tym on używa czegoś podobnego, ale z bardziej zwartym przykładem kodu. – comanitza

+0

Jeśli pochodzi z róży indii, powinieneś założyć, że jest w większości w porządku. Lepiej jest czytać o każdej innej stronie internetowej. –

8

Nie ma prosty sposób to zrobić z BufferedReader z powodu dwóch czynników: Charakter endcoding i zakończeń linii. W systemie Windows kończy się linia \r\n, która składa się z dwóch bajtów. W systemie Unix separator linii jest pojedynczym bajtem. BufferedReader obsłuży oba przypadki, nie zauważając, więc po readLine() nie będzie wiadomo, ile bajtów zostało pominiętych.

Również buffer.getBytes() zwraca prawidłowy wynik tylko wtedy, gdy domyślne kodowanie i kodowanie danych w pliku przypadkowo jest takie samo. Podczas konwersji dowolnego rodzaju należy zawsze dokładnie określić, które kodowanie powinno być używane.

Nie można również użyć zliczania InputStream, ponieważ buforowane czytniki odczytują dane w dużych porcjach. Więc po przeczytaniu pierwszego wiersza z, powiedzmy, 5 bajtami, licznik w wewnętrznej InputStream zwróci 4096, ponieważ czytnik zawsze odczytuje wiele bajtów do swojego wewnętrznego bufora.

Możesz na to spojrzeć na NIO. Możesz użyć niskiego poziomu ByteBuffer, aby śledzić przesunięcie i zawijanie, które w CharBuffer przekształca dane wejściowe w linie.

+0

Nie ma prostego sposobu na zrobienie tego z BufferedReader, ponieważ wykonuje on zarówno buforowanie, jak i wykrywanie nowej linii. BTW, dzięki za podpowiedź na temat ByteBuffer i CharBuffer –

0

Zastanawiam się nad ostatecznym rozwiązaniem, jednak myślę, że używanie długiego typu zamiast int może spełnić większość sytuacji w powyższym kodzie.