2009-05-06 9 views
2

Ich versuche, UTF-8 aus einer Textdatei zu lesen und einige tokenization zu tun, aber ich habe Probleme mit der Codierung:Lesen von Daten von UTF-8-Textdatei und tokenize

try { 
    fis = new FileInputStream(fName); 
} catch (FileNotFoundException ex) { 
    //... 
} 

DataInputStream myInput = new DataInputStream(fis); 
    try { 
     while (thisLine = myInput.readLine()) != null) { 
      StringTokenizer st = new StringTokenizer(thisLine, ";"); 
      while (st.hasMoreElements()) { 
      // do something with st.nextToken(); 
    } 
} 
} catch (Exception e) { 
//... 
} 

und Datainputstream hat keine Parameter um die Kodierung einzustellen!

+0

Eine grobe Orientierung zu Java-Zeichencodierung: http://illegalargumentexception.blogspot.com/2009/05/java-rough-guide-to-character-encoding.html – McDowell

Antwort

5

Lassen Sie mich für diese Methode geben Sie die Javadoc gut funktionieren würde.

DataInputStream.readLine()

aufgegeben. Diese Methode konvertiert nicht korrekt Bytes in Zeichen. Ab JDK 1.1 ist der bevorzugte Weg zu Lesen von Textzeilen über die BufferedReader.readLine() -Methode. Programme, die die Datainputstream Klasse verwenden Zeilen lesen kann die BufferedReader-Klasse von ersetzen Code des Formulars zu verwenden umgewandelt werden:

 DataInputStream d = new DataInputStream(in); 

mit:

 BufferedReader d 
      = new BufferedReader(new InputStreamReader(in)); 

BTW: JDK 1.1 kam im Februar 1997 heraus, also sollte das für Sie nicht neu sein.

Denken Sie nur daran, wie viel Zeit alle gespeichert hätten, wenn Sie den Javadoc gelesen hätten. ;)

1

Warum nicht InputStreamReader verwenden und die Codierung angeben? Sie können dann mit einem BufferedReader umbrechen, um die readLine() - Funktion bereitzustellen.

4

können Sie Input verwenden:

BufferedReader br = new BufferedReader (new InputStreamReader (source, charset); 
while (br.readLine() != null) { ... } 

Sie auch Scanner versuchen können, aber ich bin nicht sicher, dass es

0

Wenn Sie Text (nicht binäre Daten) lesen, sollten Sie einen Reader (keinen InputStream) verwenden. Sie können die Codierung für die VM angeben, indem Sie -Dfile.encoding = utf-8 ausführen. Der Reader wird diese Codierung automatisch verwenden. So könnte man die Kodierung einfach wechseln. Sie können BufferedReader in FileReader verwenden, um eine readLine() zu erhalten. Die Methode readline() hat nur Sinn, wenn das Lesen von Text sonst die Zeilenenden sind nur die Bytes

+0

die Standardcodierung über den Leitungsänderungsbefehl (-dfile .encoding = ...) ist in Ordnung für kleine Dienstprogramme, kann aber unerwünschte Nebenwirkungen für Interaktionen mit dem System haben - zum Beispiel für System.out. – McDowell

+0

Für mich klang es wie ein kleines Dienstprogramm. So gewinnen Sie eine Menge Flexibilität, indem Sie Java die Magie machen lassen. Sie haben Recht, dass es keine gute Idee ist, die Kodierung auf eine größere Anwendung umzustellen, aber codierte Kodierungen in Ihrem Code sind nicht viel besser. Wenn Sie file.encoding nicht angeben, was zu dem Ergebnis führt, dass es aus dem System übernommen wird, werden Sie auch nicht vor Nebeneffekten geschützt –

0

Eine sehr einfache Art und Weise:

File myFile = ... 

String contents = Files.toString(myFile, Charsets.UTF_8); 
for (String token : contents.split(";")) { 
    // do something with token 
} 

Wo Files und Charsets sind von Guava. Oder wenn Sie die Datei Zeile für Zeile verarbeiten müssen, beginnen Sie mit diesem statt:

List<String> lines = Files.readLines(myFile, Charsets.UTF_8); 

Beachten Sie auch, dass split() einfacher ist, hier zu verwenden, als StringTokenizer.

Know and use the libraries, wie ich es gerne gesagt habe. (Natürlich kann das Lesen der gesamten Datei auf einmal nicht für alle Situationen geeignet sein.)

Bearbeiten (2013): Schaltete meine Empfehlung von Apache Commons IO nach Guava, die insgesamt sauberer und aktivere Bibliothek verwaltet wird.

0

StringTokenizer ist eine extrem einfache Klasse für die Text-Tokenisierung, ich kann sie nur für Aufgaben empfehlen, die die Token nicht weiter identifizieren müssen (d. H. Mit einem Wörterbuch-Lookup) und die nur für westliche Sprachen verwendet werden.

Für weitergehende Fälle in westlichen Sprachen kann ein einfacher Tokenizer basierend auf Unicode-Zeichenklassen geschrieben werden (dies wird viele Arten von Leerzeichen aufnehmen, Zeichen abgrenzen usw.) und dann mit Regexes erweitert, um spezielle Fälle zu fangen (wie ' das ist ',' C++ '...).