Java NIO & the iTunes Database
by Dmitriy Rogatkin

             
Listing One
public Object get(int index) {
   if (index >= START_OBJ_INDEX && index <= END_OBJ_IDX)
      return objValues[index - START_OBJ_INDEX];
   if (index >= START_INT_INDEX && index <= END_INT_IDX)
      return new Integer(intValues[index - START_INT_INDEX]);
   throw new IllegalArgumentException("Index " + index + " is out of range.");
}
public int getInt(int index) {
   if (index >= START_INT_INDEX && index <= END_INT_IDX)
     return intValues[index - START_INT_INDEX];
   throw new IllegalArgumentException("Index " + index + " is out of range.");
}
 
Listing Two
public int read(FileChannel fileChannel, int readPosition) throws IOException {
   ByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 
                     readPosition, getSize()).order(ByteOrder.LITTLE_ENDIAN);
   intValues[SIGNATURE] = buffer.getInt();
   if (getSignature() != intValues[SIGNATURE])
   throw new IOException(
      "Unexpected signature 0x"
      + Integer.toHexString(intValues[SIGNATURE])
      + "("
      + asString(intValues[SIGNATURE])
      + ") where 0x"
      + Integer.toHexString(getSignature())
      + " was expected.");
   intValues[SIZE] = buffer.getInt();
   if (buffer.capacity() < intValues[SIZE])
      throw new IOException("Real header size " + intValues[SIZE] + " 
                                            exceeds the buffer capacity.");
   readSpecific(buffer);
      return readPosition + intValues[SIZE];
}

 
Listing Three
public void read(FileChannel fileChannel) throws IOException {
   ByteBuffer buffer = 
   ByteBuffer.allocateDirect(8).order(ByteOrder.LITTLE_ENDIAN);
   fileChannel.read(buffer);
   buffer.rewind();
   intValues[SIGNATURE] = buffer.getInt();
   if (getSignature() != intValues[SIGNATURE])
      throw new IOException(
         "Unexpected signature 0x"
        + Integer.toHexString(intValues[SIGNATURE])
        + "("
        + asString(intValues[SIGNATURE])
        + ") where 0x"
        + Integer.toHexString(getSignature())
        + " was expected.");
   intValues[SIZE] = buffer.getInt();
   buffer = 
       ((ByteBuffer)ByteBuffer.allocateDirect(intValues[SIZE]).position(8)).
                                               order(ByteOrder.LITTLE_ENDIAN);
   fileChannel.read(buffer);
   buffer.position(8);
   if (buffer.capacity() < intValues[SIZE])
      throw new IOException("Real header size " + intValues[SIZE] + " 
                                              exceeds the buffer capacity.");
   readSpecific(buffer);
}
 
Listing Four
public void read(ByteBuffer buffer) throws IOException {
   intValues[SIGNATURE] = buffer.getInt();
   if (getSignature() != intValues[SIGNATURE])
      throw new IOException(
         "Unexpected signature 0x"
         + Integer.toHexString(intValues[SIGNATURE])
         + "("
         + asString(intValues[SIGNATURE])
         + ") where 0x"
         + Integer.toHexString(getSignature())
         + " was expected.");
   intValues[SIZE] = buffer.getInt();
   readSpecific(buffer);
   buffer = ((ByteBuffer) 
   buffer.position(intValues[SIZE])).slice().order(ByteOrder.LITTLE_ENDIAN);
   readChildren(buffer);
}

 
Listing Five
public void readSpecific(ByteBuffer buffer) {
   intValues[SIZE] = getSize(); // 16
   intValues[NUM_ENTRIES] = buffer.getInt();
   intValues[LENGTH] = buffer.getInt();
   intValues[TOTAL_SIZE] = intValues[LENGTH] + intValues[SIZE];
   objValues[DATA - START_OBJ_INDEX] = ((ByteBuffer) 
    buffer.position(intValues[SIZE]).
limit(intValues[SIZE]+intValues[LENGTH])).asCharBuffer().toString();
}


Listing Six
public static final String ITUNESDB_PATH = 
   File.separator + "iPod_Control" + 
   File.separatorChar + "iTunes" +
   File.separatorChar + "iTunesDB";
   String drive = "H:";
   FileChannel fileChannel = new FileInputStream(drive +
                               ITUNESDB_PATH).getChannel();






1


