Файл произвольного доступа и дополнительные символы ASCII в Java

У меня есть файл произвольного доступа, заполненный строками (я знаю, что на самом деле это не строки, хотя это поможет мне объяснить проблему). Что я хочу сделать, так это просмотреть определенную строку, скажем, строку № 4. В то время как это было бы просто для целых чисел и вообще примитивных типов данных, поскольку они имеют фиксированную длину байта, и я могу прочитать правильные байты, суммируя все предыдущие байты.

Мне удалось решить эту проблему, придав всей строке фиксированную длину 16 символов, поэтому, если у меня есть слово «собака», то это слово в RAF «собака» (собака + 13 пробелов), а длина в байтах была исправлено тоже. Опять же, я мог легко прочитать правильное значение, используя следующий метод:

static String loadOne(int n) throws IOException {
    raf = new RandomAccessFile(file, "rw");
    raf.seek((n-1)*(fix+2));
    String x = raf.readUTF();
    return x;
}

Где n — это номер значения, которое я хочу прочитать, а fix — это количество символов (и байтов) в одной строке.

Все было хорошо, пока я не использовал дополнительный символ ASCII — польскую букву — в одной из строк, потому что она состоит из 2 байтов. Длина char осталась прежней - 16, но было 17 байт и все развалилось.

Что я могу сделать?


person ngr900    schedule 07.12.2012    source источник


Ответы (1)


Я сильно подозреваю, что вы используете readUTF не так, как ожидается. Вы точно читали, что он делает?

Первые два байта читаются, начиная с текущего указателя файла, как будто readUnsignedShort. Это значение дает количество следующих байтов в закодированной строке, а не длину результирующей строки. Следующие байты затем интерпретируются как байты, кодирующие символы в модифицированном формате UTF-8, и преобразуются в символы.

Соответствует ли это тому, что хранится в вашем файле? (Вы ничего не указали о формате файла.)

Учитывая, что UTF-8 не имеет фиксированной ширины, это звучит неуместно для вашего сценария.

Я бы предложил использовать 32 байта на запись, что всегда будет давать 16 значений char в виде кодовых единиц UTF-16. Вы можете очень просто преобразовать это, используя new String(data, "UTF-16BE") и text.getBytes("UTF-16BE") (или используйте LE вместо BE, если хотите). Таким образом, вы получите строку действительно фиксированной длины в байтах, а не только в символах.

person Jon Skeet    schedule 07.12.2012