// =========================================================
// Прямой доступ к файлу с помощью класса RandomAccessFile
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW:    http://www.glasnet.ru/~frolov
//            или
//         http://www.dials.ccas.ru/frolov
// =========================================================
import java.io.*;
import java.util.*;

// =========================================================
// Класс DirectFileAccess
// Главный класс приложения
// =========================================================
public class DirectFileAccess
{
  // -------------------------------------------------------
  // main
  // Метод, получающий управление при запуске приложения
  // -------------------------------------------------------
  public static void main(String args[])
  {
    // Массив для ввода строки с клавиатуры
    byte bKbdInput[] = new byte[256];

    try
    {
      // Создаем новую базу данных
      SimpleDBMS db = new SimpleDBMS("dbtest.idx", "dbtest.dat");
      
      // Добавляем в нее три записи
      db.AddRecord("Ivanov",   1000);
      db.AddRecord("Petrov",   2000);
      db.AddRecord("Sidoroff", 3000);
 
      // Получаем и отображаем содержимое первых трез
      // записей с номерами 2, 1 и 0
      System.out.println(db.GetRecordByNumber(2));
      System.out.println(db.GetRecordByNumber(1));
      System.out.println(db.GetRecordByNumber(0));

      // Закрываем базу данных
      db.close();
      
      // После ввода любой строки завершаем работу программы
      System.out.println("Press <Enter> to terminate...");
      System.in.read(bKbdInput);
    }
    catch(Exception ioe)
    {
      System.out.println(ioe.toString());
    }
  }
}

// =========================================================
// Класс SimpleDBMS
// Простейшая база данных
// =========================================================
class SimpleDBMS
{
  // Файл индексов
  RandomAccessFile idx;

  // Файл данных
  RandomAccessFile dat;

  // Значение указателя на текущую запись
  long idxFilePointer = 0;

  // -------------------------------------------------------
  // SimpleDBMS
  // Конструктор. Создает и открывает файлы базы данных
  // -------------------------------------------------------
  public SimpleDBMS(String IndexFile, String DataFile)
  {
    try
    {
      // Создаем и открываем файл индексов
      idx = new RandomAccessFile(IndexFile, "rw");

      // Создаем и открываем файл данных
      dat = new RandomAccessFile(DataFile, "rw");
    }
    catch(Exception ioe)
    {
      System.out.println(ioe.toString());
    }
  }

  // -------------------------------------------------------
  // close
  // Метод close. Закрывает файлы базы данных
  // -------------------------------------------------------
  public void close()
  {
    try
    {
      // Закрываем файл индексов
      idx.close();

      // Закрываем файл данных
      dat.close();
    }
    catch(Exception ioe)
    {
      System.out.println(ioe.toString());
    }
  }

  // -------------------------------------------------------
  // AddRecord
  // Добавление записи в базу данных
  // -------------------------------------------------------
  public void AddRecord(String name, int account)
  {
    try
    {
      // Устанавливаем текущую позицию в файлах
      // индекса и данных на конец файла
      idx.seek(idx.length());
      dat.seek(dat.length());

      // Получаем смещение в файле данных на то место,
      // куда будет добавлена новая запись
      idxFilePointer = dat.getFilePointer();

      // Сохраняем это смещение в файле индексов
      idx.writeLong(idxFilePointer);

      // Сохраняем в файле дайнных два поля новой записи
      dat.writeBytes(name + "\r\n");
      dat.writeInt(account);
    }
    catch(Exception ioe)
    {
      System.out.println(ioe.toString());
    }
  }

  // -------------------------------------------------------
  // GetRecordByNumber
  // Извлечение записи по ее порядковому номеру
  // -------------------------------------------------------
  public String GetRecordByNumber(long nRec)
  {
    // Строка, в которой будет сохранена извлеченная запись
    String sRecord = "<empty>";
 
    try
    {
      // Значение поля account
      Integer account;

      // Значение поля name
      String str = null;

      // Вычисляем смещение в файле индексов по порядковому
      // номеру записи
      idx.seek(nRec * 8);

      // Извлекаем из файла индексов смещение записи
      // в файле данных
      idxFilePointer = idx.readLong();

      // Выполняем позиционирование на нужную запись
      // в файле данных
      dat.seek(idxFilePointer);
  
      // Извлекаем поля записи
      str = dat.readLine();
      account = new Integer(dat.readInt());

      // Объединяем значения полей в текстовую строку
      sRecord = new String("> " + account + ", " + str);
    }
    catch(Exception ioe)
    {
      System.out.println(ioe.toString());
    }

    // Возвращаем извлеченную запись
    return sRecord;
  }
}