2008-09-18 14 views
5

Je le code suivant:Lecture d'un fichier ASCII avec FileChannel et 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(); 
     } 

Mais de personnages ne sera pas affiché à?. Cela a-t-il quelque chose à voir avec Java en utilisant des caractères Unicode? Comment est-ce que je corrige ceci?

Répondre

7

Vous devez connaître le codage du fichier, puis décoder le ByteBuffer dans un CharBuffer à l'aide de ce codage. En supposant que le fichier est 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

Si vous voulez éviter d'imprimer chaque caractère séparément, vous pouvez simplement utiliser 'buf.flip()' au lieu de 'buf.rewind()', et passer tout le chbuf à 'System.out.print()' – hertzsprung

0

Oui, c'est Unicode.

Si vous avez 14 caractères dans votre fichier, vous obtenez seulement 7 '?'.

Solution en attente. Encore en train de penser.

1

Y a-t-il une raison particulière pour laquelle vous lisez le fichier comme vous le faites?

Si vous lisez un fichier ASCII, vous devriez vraiment utiliser un lecteur.

je le ferais quelque chose comme:

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

Et puis utilisez soit readLine ou similaire à lire réellement dans les données!

+1

J'ai une énorme quantité de données, et j'essaie d'optimiser le temps de lecture. Référence: http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly – Jake

+0

@Jake, dans votre exemple, vous lisez les octets, puis décoder en caractères. Pourquoi supposez-vous que c'est plus rapide que d'utiliser un BufferedReader? Les repères intéressants que vous pointez ne lisent pas les caractères. –

2

Changer votre déclaration d'impression:

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

Semble aider.

3

buf.getChar() attend 2 octets par caractère, mais vous stockez seulement 1. Utilisation:

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

vous avez oublié de modifier le code, il lit toujours .get() –

2

Selon le codage de somefile.txt, un caractère ne peut pas réellement être composé de deux octets . This page donne plus d'informations sur la façon de lire les flux avec le codage approprié. Le Bummer est, le système de fichiers ne vous dit pas l'encodage du fichier, car il ne sait pas. En ce qui le concerne, c'est juste un tas d'octets. Vous devez soit trouver un moyen de communiquer l'encodage au programme, soit le détecter d'une manière ou d'une autre, ou (si possible) toujours vous assurer que l'encodage est le même (comme UTF-8).

Questions connexes