Документы API говорят следующее для readUTF8
Читает строку из этого файла. Строка была закодирована с использованием
модифицированный формат UTF-8.
Первые два байта считываются, начиная с текущего указателя файла,
как будто с помощью readUnsignedShort. Это значение дает число следующих
байты в зашифрованной строке, а не длина результирующего
строка. Следующие байты затем интерпретируются как байтовая кодировка
символы в измененном формате UTF-8 и преобразуются в
символы.
Этот метод блокируется, пока все байты не будут прочитаны, конец потока
Обнаружено или выдано исключение.
Ваша строка отформатирована таким образом?
Похоже, это объясняет ваш EOF, за исключением.
Ваш файл представляет собой текстовый файл, поэтому ваша настоящая проблема заключается в декодировании.
Простейший ответ, который я знаю:
try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("jedis.txt"),"UTF-8"))){
String line = null;
while( (line = reader.readLine()) != null){
if(line.equals("Obi-wan")){
System.out.println("Yay, I found " + line +"!");
}
}
}catch(IOException e){
e.printStackTrace();
}
Или вы можете установить текущую системную кодировку с системным свойством file.encoding
в UTF-8.
java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ...
Вы также можете установить его как системное свойство во время выполнения с System.setProperty(...)
, если вам это нужно только для этого конкретного файла, но в таком случае, как я думаю, я бы предпочел OutputStreamWriter
.
Установив системное свойство, вы можете использовать FileReader
и ожидать, что оно будет использовать UTF-8 в качестве кодировки по умолчанию для ваших файлов. В этом случае для всех файлов, которые вы читаете и пишете.
Если вы намереваетесь обнаружить ошибки декодирования в вашем файле, вам придется использовать подход InputStreamReader
и использовать конструктор, который получает декодер.
В некотором роде
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
BufeferedReader out = new BufferedReader(new InpuStreamReader(new FileInputStream("jedis.txt),decoder));
Вы можете выбирать между действиями IGNORE | REPLACE | REPORT
EDIT
Если вы настаиваете на использовании RandomAccessFile
, вам необходимо знать точное смещение линии, которую вы собираетесь читать. И не только это, чтобы читать методом readUTF()
, вы должны были записать файл методом writeUTF()
. Поскольку этот метод, как указано выше в JavaDocs, ожидает определенного форматирования, в котором первые 2 байта без знака представляют длину в байтах строки UTF-8.
Как таковой, если вы делаете:
try(RandomAccessFile raf = new RandomAccessFile("jedis.bin", "rw")){
raf.writeUTF("Luke\n"); //2 bytes for length + 5 bytes
raf.writeUTF("Obiwan\n"); //2 bytes for length + 7 bytes
raf.writeUTF("Yoda\n"); //2 bytes for lenght + 5 bytes
}catch(IOException e){
e.printStackTrace();
}
У вас не должно возникнуть проблем при чтении из этого файла с использованием метода readUTF()
, если вы можете определить смещение заданной строки, которую вы хотите прочитать.
Если вы откроете файл jedis.bin
, вы заметите , это двоичный файл , а не текстовый файл.
Теперь я знаю, что "Luke\n"
- это 5 байтов в UTF-8, а "Obiwan\n"
- это 7 байтов в UTF-8. И что метод writeUTF()
вставит 2 байта перед каждой из этих строк. Следовательно, до "Yoda\n"
(5 + 2) + (7 + 2) = 16 байт.
Итак, я мог бы сделать что-то подобное, чтобы добраться до последней строки:
try (RandomAccessFile raf = new RandomAccessFile("jedis.bin", "r")) {
raf.seek(16);
String val = raf.readUTF();
System.out.println(val); //prints Yoda
} catch (IOException e) {
e.printStackTrace();
}
Но это не будет работать, если вы записали файл с классом Writer
, потому что авторы не следуют правилам форматирования метода writeUFT()
.
В таком случае лучше всего, чтобы ваш двоичный файл был отформатирован таким образом, чтобы все строки занимали одинаковое количество места (число байтов, а не количество символов, потому что количество байтов является переменным в UTF-8 в зависимости от символов в вашей строке), если не все пространство необходимо, вы его дополняете:
Таким образом, вы можете легко вычислить смещение данной линии, поскольку все они будут занимать одинаковое количество места.