Чтение файла ASCII с помощью FileChannel и ByteArrays
-
01-07-2019 - |
Вопрос
У меня есть следующий код:
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();
}
Но символы отображаются через ?.Имеет ли это какое-то отношение к Java, использующему символы Юникода?Как мне это исправить?
Решение
Вы должны знать, какова кодировка файла, а затем декодировать ByteBuffer в CharBuffer, используя эту кодировку.Предполагая, что файл имеет формат 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();
}
}
}
Другие советы
buf.getChar() ожидает 2 байта на символ, но вы сохраняете только 1.Использовать:
System.out.print((char) buf.get());
Изменение оператора печати на:
System.out.print((char)buf.get());
Кажется, помогает.
В зависимости от кодировки файла somefile.txt символ может фактически не состоять из двух байтов. Эта страница дает дополнительную информацию о том, как читать потоки с правильной кодировкой.
Облом в том, что файловая система не сообщает вам кодировку файла, потому что она не знает.Насколько это возможно, это всего лишь набор байтов.Вы должны либо найти способ сообщить кодировку программе, каким-то образом обнаружить ее, либо (если возможно) всегда гарантировать, что кодировка одинакова (например, UTF-8).
Есть ли особая причина, по которой вы читаете файл именно так?
Если вы читаете файл ASCII, вам действительно следует использовать Reader.
Я бы сделал это примерно так:
File inputFile = new File("somefile.txt");
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
А затем используйте либо readLine
или что-то подобное, что действительно читается в данных!
Да, это Юникод.
Если в вашем файле 14 символов, вы получите только 7 '?'.
Решение ожидается.Еще думаю.