2008-09-18 25 views
5

Mam następujący kod:Odczytywanie pliku ASCII z FileChannel i ByteArrays

 String inputFile = "somefile.txt"; 
     FileInputStream in = new FileInputStream(inputFile); 
     FileChannel ch = in.getChannel(); 
     ByteBuffer buf = ByteBuffer.allocateDirect(BUFSIZE); // BUFSIZE = 256 

     /* read the file into a buffer, 256 bytes at a time */ 
     int rd; 
     while ((rd = ch.read(buf)) != -1) { 
      buf.rewind(); 
      for (int i = 0; i < rd/2; i++) { 
       /* print each character */ 
       System.out.print(buf.getChar()); 
      } 
      buf.clear(); 
     } 

Ale znaki uzyskać wyświetlane w 's. Czy ma to coś wspólnego z Javą używającą znaków Unicode? Jak mogę to poprawić?

Odpowiedz

7

Musisz wiedzieć, jakie jest kodowanie pliku, a następnie odkodować ByteBuffer na CharBuffer używając tego kodowania. Zakładając, że plik jest ASCII:

import java.util.*; 
import java.io.*; 
import java.nio.*; 
import java.nio.channels.*; 
import java.nio.charset.*; 

public class Buffer 
{ 
    public static void main(String args[]) throws Exception 
    { 
     String inputFile = "somefile"; 
     FileInputStream in = new FileInputStream(inputFile); 
     FileChannel ch = in.getChannel(); 
     ByteBuffer buf = ByteBuffer.allocateDirect(BUFSIZE); // BUFSIZE = 256 

     Charset cs = Charset.forName("ASCII"); // Or whatever encoding you want 

     /* read the file into a buffer, 256 bytes at a time */ 
     int rd; 
     while ((rd = ch.read(buf)) != -1) { 
      buf.rewind(); 
      CharBuffer chbuf = cs.decode(buf); 
      for (int i = 0; i < chbuf.length(); i++) { 
       /* print each character */ 
       System.out.print(chbuf.get()); 
      } 
      buf.clear(); 
     } 
    } 
} 
+0

Jeśli chcesz uniknąć drukowania każdego znaku osobno, możesz po prostu użyć 'buf.flip()' zamiast 'buf.rewind()' i przekazać cały chbuf do 'System.out.print()' – hertzsprung

0

Tak, jest to kod Unicode.

Jeśli masz 14 znaków w swoim pliku, dostajesz tylko 7 "?".

Rozwiązanie w toku. Wciąż myślę.

1

Czy istnieje szczególny powód, dla którego czytasz plik w taki sposób, w jaki robisz?

Jeśli czytasz w pliku ASCII, naprawdę powinieneś używać Czytnika.

chciałbym zrobić coś takiego:

File inputFile = new File("somefile.txt"); 
BufferedReader reader = new BufferedReader(new FileReader(inputFile)); 

a następnie użyć albo readLine lub podobny faktycznie czytać w danych!

+1

Mam olbrzymią ilość danych i staram się zoptymalizować czas czytania. Odnośnik: http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly – Jake

+0

@Jake, w twoim przykładzie czytasz bajty, a następnie dekodujesz do znaków. Dlaczego zakładasz, że jest to szybsze niż użycie BufferedReader? Interesujące punkty odniesienia, na które wskażecie, nie czytają postaci. –

2

Zmiana oświadczenie wydruku:

System.out.print((char)buf.get()); 

wydaje się pomagać.

3

buf.getChar() spodziewa 2 bajty na znak, ale są przechowywane tylko 1. Zastosowanie:

System.out.print((char) buf.get()); 
+0

zapomniałeś zmodyfikować kod, nadal czyta .get() –

2

zależności od kodowania somefile.txt, postać nie może być w rzeczywistości składa się z dwóch bajtów . This page podaje więcej informacji o tym, jak odczytywać strumienie z odpowiednim kodowaniem.

Opóźnienie jest, system plików nie mówi kodowania pliku, ponieważ nie wie. O ile to dotyczy, to tylko kilka bajtów. Musisz albo znaleźć jakiś sposób, aby zakomunikować kodowanie do programu, jakoś go wykryć, albo (jeśli to możliwe) zawsze upewnić się, że kodowanie jest takie samo (jak na przykład UTF-8).