Чтение определенного индекса из двоичного файла, содержащего массив объектов

У меня есть двоичный файл, созданный в программе Java. Двоичный файл содержит массив объектов User.

Он был создан так:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {
    public static void main(String[] args) {

        User[] arrayOfUsers = new User[50];
        for (int i = 0; i < 50; i++){
            arrayOfUsers[i] = new User("Mr. ", i + "owitz");
        }

        try {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users.dat"));
            oos.writeObject(arrayOfUsers);
            oos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

Это User учебный класс:

import java.io.Serializable;

public class User implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    private String firstname;
    private String lastname;
    public User(String firstname, String lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }



}

На данный момент я знаю, как читать только весь массив одновременно. Тем не менее, мне обычно нужно получить только один или два User объекты из массива, и я знаю их позиции.

Есть ли способ прочитать только индекс, который я хочу прочитать, не читая во всем?

1 ответ

Решение

Вы создаете не прямой файл, а просто последовательный файл, который содержит сериализуемую версию Java ArrayList. Таким образом, вы можете только прочитать весь ArrayList в памяти, чтобы снова обработать его и получить доступ к отдельному элементу.

Если вы хотите иметь доступ непосредственно к элементу, просто зная его индекс, вам нужно будет создать настоящий прямой файл или индексированный файл. Прямой файл имеет записи постоянного размера, скажем sИтак, смещение для записи n является n * s, Вы можете использовать его через класс Java RandomAccessFile, Но вы не должны напрямую использовать readUTF или же writeUTF для прямых файлов, потому что длина строки в байтах зависит от количества и типа символов:

  • Все символы в диапазоне от \u0001 до \u007F представлены одним байтом
  • Нулевой символ "\u0000" и символы в диапазоне от "\u0080" до "\u07FF" представлены парой байтов
  • Значения символов в диапазоне от \u0800 до \uFFFF представлены тремя байтами

(ссылка: Javadoc для DataInput)

Так что вам лучше явно конвертировать их в byte[] с String.getBytes() по крайней мере, теперь легче контролировать размер и вручную записывать размер, а не байты. В качестве альтернативы, вы можете написать пропустить преобразование в байтах, записать размер в Char а затем напишите отдельные символы.


Если вы почти никогда не изменяете значения или не добавляете значения, вы можете использовать индексированный файл. Основа состоит в том, чтобы сначала иметь массив, содержащий смещения записей. Это позволяет записям не иметь одинаковый размер. Возможный дизайн будет:

  1. количество записей в массиве смещений (int n)
  2. n int для смещений
  3. данные

Чтобы записать файл, вы вычисляете начало области данных: (1 + n) * 4, создайте массив int для хранения смещений. Тогда ты пишешь n+1 0 чтобы файл был правильно позиционирован, и запишите свою строку, последовательно сохраняя позицию записи для первой записи. Наконец вы возвращаетесь к 0, записываете количество записей и смещений.

Чтобы прочитать, просто прочитайте количество записей и смещений. Затем вы можете перемещаться по файлу. Это в основном используется для больших записей неизвестных и переменных размеров


И если вы обнаружите, что вышеупомянутое слишком сложно, просто используйте базы данных. Derby или H2 могут использоваться как встроенные базы данных, и это будет намного проще.

Другие вопросы по тегам