# Integer aus Datei lesen u.a. Probleme



## javaprogger1987 (6. Juni 2006)

Hallo!

Ich hab folgendes Problem ich bin mir nicht sicher ob ich Integer korrekt aus einer Datei auslese..
Mein Ziel ist es, die Winamp Media Library Dateien zu lesen, allerdings scheitert es irgendwie an meinem Verständnis.. Naja erstmal hier die Spezefikation der Library:
http://www.bluemars.org/sdk/extra/nde_specs_v1.txt

Nun dachte ich, dass ich bei der Indexdatei folgendermaßen vorgehen muss (Punkt 2 in der Doku):
1. 8 Byte String lesen ("NDEINDEX") -> klappt
2. 4 Byte Integer lesen
3. So oft 4 Byte Integer lesen wie der voherige Integer groß ist (Array)

Nun fang ich aber schon an Punkt 2 an zu zweifeln ob ich das so richtig mache, denn irgendwie ist die Zahl zwar ganz ok (8922, meine ML hat 8920 Einträge) aber irgendwie passt das vorne und hinten nicht bei Punkt 3..

Meine Integer-Lese-Funktion ^^:

```
private int readInt( RandomAccessFile raf ) throws IOException
  {
    int ret = 0;
    int[] bytes = new int[4]; //4 Byte Integer lesen
    for ( int i = 0; i < 4; i++ )
    {
      bytes[i] = raf.readUnsignedByte();
    }
    //Da LittleEndian -> richtige Reihenfolge einhalten
    for ( int i = 3; i >= 0; i-- )
    {
      ret = ret << 8;
      ret = ret | bytes[i];
    }
    return ret;
  }
```

Die ersten Integers des Arrays von 3. sehen so aus
	
	
	



```
255
8
0
429
1
487
8921
898
8920
1305
8919
1710
8918
2105
8917
```

Ab 8921 scheint mir das auch ganz sinnvoll zu sein (Eintragnr + Offset in der Data-Datei) aber so steht das ja nicht in der Spezefikation und ich kann mir die Zahlen davor auch nicht erklären .. Vllt. könntet Ihr euch das mal angucken 

Gruß
Tobias


----------



## flashray (6. Juni 2006)

Hallo Tobias,

kennst du DataInputStream{} - readInt() ? Damit kann man standartmäßig einen gewünschten Datentyp einlesen.
http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataInputStream.html

Ob das dir zu deinem spezifischen Problem weiterhilft, weiß ich aber nicht  .


Vg Erdal


----------



## javaprogger1987 (6. Juni 2006)

Schonmal danke für die Antwort 
Ja.. eine RandomAccessFile hat auch diese Methode.. Nur das Problem ist, dass ich, wenn ich die benutze (Hab gerade auch mal DataInputStream getestet) die Zahl -635305984 rausbekomme  Und das kann ja nicht richtig sein - deshalb hab ich mir selber grad eine gebastelt, ich vermute Java liest die Integers standartmäßig nach Big Endian (http://de.wikipedia.org/wiki/Byte-Reihenfolge) und der Integer ist da aber in Little Endian gespeichert..

Gruß
Tobias


----------



## Thomas Darimont (7. Juni 2006)

Hallo!

Mit Integer.reverseBytes(...) gings einfacher 

Gruss Tom


----------



## javaprogger1987 (7. Juni 2006)

Mist  War ja klar das es wieder einfacher geht 
Vielen Dank 

Weißt du vllt auch noch ob ich die Spezefikation der Datei falsch verstehe - denn da bin ich immer noch nicht weiter  

Gruß
Tobias


----------



## Thomas Darimont (7. Juni 2006)

Hallo!

Ich versuch heute Abend mal ein kleines Interface dazu zu bauen.
Ich lese das index-File bisher wie folgt aus:

```
/**
 * 
 */
package de.tutorials;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

/**
 * @author Tom
 *
 */
public class WinampIndexFileReaderExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception{
        File indexFile = new File("C:/Program Files/Winamp/Plugins/ml/main.idx");
        DataInputStream indexFileDataInputStream = new DataInputStream(new FileInputStream(indexFile));
        
        System.out.println(readString(indexFileDataInputStream,8));
        int numberOfRecords = readNumberOfRecords(indexFileDataInputStream);
        System.out.println(numberOfRecords);
        int[] recordIndices = readRecordIndeces(indexFileDataInputStream,numberOfRecords);        
        System.out.println(Arrays.toString(recordIndices));
        indexFileDataInputStream.close();
        
        File dataFile = new File("C:/Program Files/Winamp/Plugins/ml/main.dat");
        DataInputStream dataFileDataInputStream = new DataInputStream(new FileInputStream(indexFile));
        System.out.println(readString(dataFileDataInputStream,8));
        
        
        dataFileDataInputStream.close();
    }

    private static int[] readRecordIndeces(DataInputStream dataInputStream, int numberOfRecords) throws IOException {
            int[] recordIndices = new int[numberOfRecords];
            for (int i = 0; i < numberOfRecords; i++) {
                recordIndices[i] = Integer.reverseBytes(dataInputStream.readInt());
            }            
            return recordIndices;
    }

    private static int readNumberOfRecords(DataInputStream dataInputStream)  throws IOException{
        return Integer.reverseBytes(dataInputStream.readInt());
    }

    /**
     * @param dataInputStream
     * @param length 
     * @throws IOException
     */
    private static String readString(DataInputStream dataInputStream, int length) throws IOException {
        byte[] ndeIndex = new byte[length];
        dataInputStream.read(ndeIndex);
        StringBuilder ndeIndexString = new StringBuilder();
        for(byte b : ndeIndex){
            ndeIndexString.append((char)b);
        }
        return ndeIndexString.toString();
    }
    
    static class Record{
        final static int FIELD_UNDEFINED   = 255;
        final static int FIELD_COLUMN      = 0;
        final static int FIELD_INDEX       = 1;
        final static int FIELD_REDIRECTOR  = 2;
        final static int FIELD_STRING      = 3;
        final static int FIELD_INTEGER     = 4;
        final static int FIELD_BOOLEAN     = 5;
        final static int FIELD_BINARY      = 6;
        final static int FIELD_GUID        = 7;
        final static int FIELD_FLOAT       = 9;
        final static int FIELD_DATETIME    = 10;
        final static int FIELD_LENGTH      = 11;
        
        char columnId;
        char fieldType;
        int fieldDataSize;
        int nextFieldPosition;
        int previousFieldPosition;
        byte[] fieldData;
        
        //todo
    }
}
```

Gruss Tom


----------



## javaprogger1987 (7. Juni 2006)

Okay.. vielen Dank fürs Anschauen  Genauso hab ich das auch verstanden, soweit ich das sehe.. 

```
RandomAccessFile rafIndex = new RandomAccessFile( mlIndex, "r" );

    //Zuerst Header ueberpruefen
    byte[] buf = new byte[8];
    rafIndex.read( buf );

    if( ! ( new String( buf ).equals( HEADER_STR ) ) )
      throw new IOException( "Fehler! Keine gueltige Index Datei" );

    //Anzahl der Eintraege lesen
    int numOfRecords = readInt( rafIndex );

    int[] recordIndizes = new int[numOfRecords];

    for ( int i = 0; i < numOfRecords; i++ )
    {
      recordIndizes[i] = readInt( rafIndex );
      //System.out.println( recordIndizes[i] );
    }

    System.out.println( numOfRecords );
```

Nur bekomme ich das Array wie es oben steht dann raus.. 
Was mich dann richtig verwirrt ist in der Spezifikation weiter unten das:
	
	
	



```
* Index Field :
  ==================================================================================================
  Offset                      Data Type      Size                  Field
  ==================================================================================================
  0                           INT            4                     Offset of this index in the index file
->4                           INT            4                     Type of the field on which this index sorts (FIELD_UNDEFINED for the primary index)
  8                           UCHAR          1                     Size of index name string  
  9                           STRING         SizeOfIndexName       Public name of the index
```
Das irritiert mich etwas, denn der Begriff Primary Index taucht weiter oben schonmal auf, und FIELD_UNDEFINED(255) entspricht auch genau meinem ersten Eintrag im Feld.
Kann es sein, dass das Index Array nicht nur aus 4 Byte Integern sondern aus Elementen des Typs Index besteht?

Vielen vielen Dank nochmal 
Gruß
Tobias


----------

