В J2ME, Как переиндексировать записи в хранилище записей после удаления любой записи

Я разрабатываю приложение J2ME на основе определения местоположения и использую RMS для хранения данных.

В RecordStore когда я удаляю любую запись, базовые записи не переиндексируются. Например, если у меня есть 5 записей и я удаляю запись № 2, тогда идентификаторы записей будут {1, 3, 4, 5}. Но я хочу, чтобы идентификаторы записи после удаления были {1, 2, 3, 4}. Как мне это сделать??? Потому что recordId играет важную роль в моем приложении для извлечения и обновления записи.

2 ответа

Итак, поскольку вы сказали, что ваше хранилище записей в основном невелико (не так много данных), я бы порекомендовал просто добавить свой собственный id поле для каждой записи. Как сказал Майер, идентификатор RMS-записи на самом деле не предназначен для пересчета и изменения после создания записи. Итак, я бы использовал свой собственный.

Если каждая из ваших записей содержит:

boolean isMale
int age
String firstName

затем я просто добавил бы другое поле в начале каждой записи:

int id

Это делает ваши записи немного больше, но не намного (4 байта / запись). Если у вас будет менее 64 тыс. Записей, вы также можете использовать short для idи сохранить пару байтов.

Вот пример ( адаптированный из этого руководства IBM) чтения, записи и удаления с помощью записей такого типа:

   private RecordStore _rs;

   // these next two methods are just small optimizations, to allow reading and 
   //  updating the ID field in a record without the overhead of creating a new
   //  stream to call readInt() on.  this assumes the id is a 4 byte int, written
   //  as the first field in each record.

   /** Update one record with a new id field */
   private static final void putIdIntoRecord(int id, byte[] record) {      
      // we assume the first 4 bytes are the id (int)
      record[0] = (byte)(id >> 24);
      record[1] = (byte)(id >> 16);
      record[2] = (byte)(id >> 8);
      record[3] = (byte)id;
   }

   /** Get the id field from one record */
   private static final int getIdFromRecord(byte[] record) {
      // we assume the first 4 bytes are the id (int)
      return ((0xFF & record[0]) << 24) | 
            ((0xFF & record[1]) << 16) | 
            ((0xFF & record[2]) << 8) | 
            (0xFF & record[3]);
   }

   /** delete a record with the given (custom) id, re-indexing records afterwards */
   private void delete(int idToDelete) {     
      try {
         RecordEnumeration enumerator = _rs.enumerateRecords(new IdEqualToFilter(idToDelete), 
               null, false);
         _rs.deleteRecord(enumerator.nextRecordId());

         // now, re-index records after 'idToDelete'
         enumerator = _rs.enumerateRecords(new IdGreaterThanFilter(idToDelete), null, true);
         while (enumerator.hasNextElement()) {
            int recordIdToUpdate = enumerator.nextRecordId();
            byte[] record = _rs.getRecord(recordIdToUpdate);
            // decrement the id by 1
            int newId = getIdFromRecord(record) - 1;
            // copy the new id back into the record
            putIdIntoRecord(newId, record);
            // update the record, which now has a lower id, in the store
            _rs.setRecord(recordIdToUpdate, record, 0, record.length);
         }
      } catch (RecordStoreNotOpenException e) {
         e.printStackTrace();
      } catch (InvalidRecordIDException e) {
         e.printStackTrace();
      } catch (RecordStoreException e) {
         e.printStackTrace();
      }               
   }

   /** generate some record store data ... example of writing to store */
   public void writeTestData()
   {
      // just put 20 random records into the record store
      boolean[] booleans = new boolean[20];
      int[] integers = new int[20];
      String[] strings = new String[20];
      for (int i = 0; i < 20; i++) {
         booleans[i] = (i % 2 == 1);
         integers[i] = i * 2;
         strings[i] = "string-" + i;
      }

      writeRecords(booleans, integers, strings);
   }

   /** take the supplied arrays of data, and save a record for each array index */
   public void writeRecords(boolean[] bData, int[] iData, String[] sData)
   {
      try
      {
         // Write data into an internal byte array
         ByteArrayOutputStream strmBytes = new ByteArrayOutputStream();

         // Write Java data types into the above byte array
         DataOutputStream strmDataType = new DataOutputStream(strmBytes);

         byte[] record;

         for (int i = 0; i < sData.length; i++)
         {
            // Write Java data types
            strmDataType.writeInt(i);               // this will be the ID field!
            strmDataType.writeBoolean(bData[i]);
            strmDataType.writeInt(iData[i]);
            strmDataType.writeUTF(sData[i]);

            // Clear any buffered data
            strmDataType.flush();

            // Get stream data into byte array and write record
            record = strmBytes.toByteArray();            
            _rs.addRecord(record, 0, record.length);           

            // Toss any data in the internal array so writes
            // starts at beginning (of the internal array)
            strmBytes.reset();
         }

         strmBytes.close();
         strmDataType.close();
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }

   /** read in all the records, and print them out */
   public void readRecords()
   {
      try
      {
         RecordEnumeration re = _rs.enumerateRecords(null, null, false);         
         while (re.hasNextElement())
         {    
            // Get next record
            byte[] recData = re.nextRecord(); 

            // Read from the specified byte array
            ByteArrayInputStream strmBytes = new ByteArrayInputStream(recData);

            // Read Java data types from the above byte array
            DataInputStream strmDataType = new DataInputStream(strmBytes);

            // Read back the data types
            System.out.println("Record ID=" + strmDataType.readInt());
            System.out.println("Boolean: " + strmDataType.readBoolean());
            System.out.println("Integer: " + strmDataType.readInt());
            System.out.println("String: " + strmDataType.readUTF());
            System.out.println("--------------------");

            strmBytes.close();
            strmDataType.close();        
         }
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }

Здесь я использую пару небольших RecordFilter классы, используемые при поиске в хранилище записей:

   /** helps filter out records greater than a certain id */
   private class IdGreaterThanFilter implements RecordFilter {
      private int _minimumId; 
      public IdGreaterThanFilter(int value) {
         _minimumId = value;
      }
      public boolean matches(byte[] candidate) {
         // return true if candidate record's id is greater than minimum value
         return (getIdFromRecord(candidate) > _minimumId);         
      }      
   }

   /** helps filter out records by id field (not "recordId"!) */
   private class IdEqualToFilter implements RecordFilter {
      private int _id; 
      public IdEqualToFilter(int value) {
         _id = value;
      }
      public boolean matches(byte[] candidate) {
         // return true if candidate record's id matches
         return (getIdFromRecord(candidate) == _id);         
      }      
   }

Вам нужно изменить логику приложения. Идентификатор только для идентификации, а не для сортировки. Потому что это для идентификации, оно должно оставаться прежним.

Очень часто проще всего читать и писать сразу весь магазин звукозаписей.

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