Lendo um arquivo ASCII com FileChannel e bytearrays
-
01-07-2019 - |
Pergunta
Eu tenho o seguinte código:
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();
}
Mas os personagens são exibidos na? S. Será que isso tem algo a ver com Java usando caracteres Unicode? Como faço para corrigir isso?
Solução
Você tem que saber o que a codificação do arquivo é, e então decodificar o ByteBuffer em um CharBuffer usando essa codificação. Supondo que o arquivo é 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();
}
}
}
Outras dicas
buf.getChar () está esperando 2 bytes por caractere, mas você só está armazenando 1. Use:
System.out.print((char) buf.get());
Alterar sua declaração de impressão para:
System.out.print((char)buf.get());
parece ajudar.
Dependendo da codificação do somefile.txt, um personagem não pode realmente ser composta por dois bytes. Esta página dá mais informações sobre como ler streams com a codificação adequada.
A chatice é, o sistema de arquivos não dizer a codificação do arquivo, porque ele não sabe. Na medida em que está em causa, é apenas um monte de bytes. Você deve encontrar alguma maneira de comunicar a codificação para o programa, detectá-lo de alguma forma, ou (se possível) sempre garantir que a codificação é o mesmo (como UTF-8).
Existe um determinado razão pela qual você está lendo o arquivo da maneira que você faz?
Se você está lendo em um arquivo ASCII que você realmente deve estar usando um Reader.
eu faria algo como:
File inputFile = new File("somefile.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
E, em seguida, usar readLine
ou similar para realmente ler os dados!
Sim, é Unicode.
Se você tem 14 Chars em seu arquivo, você só tem 7 '?'.
Solução pendente. Ainda pensando.