# Auslesen von File - ASCII und Binärzeichen



## redbomber (13. Feb 2009)

Hi zusammen,
versuche gerade Daten aus einer Datei auszulesen.

Dies enthält erst einmal einige ASCII Zeichen, die ich auch problemlos auslesen kann.
Danach kommen dann binärdaten.
Dabei handelt es sich um Zahlen:
Diese sind vom Typ Integer, Double oder Short (dies weiss ich)
Die Anzahl der Zahlen weiss ich auch.

Nun ist meine Frage wie ich die genau auslesen kann.

Die ASCII Zeichen lese ich bisher wie folgt aus:


```
File file = new File(myWholeFileName);
			FileReader in = new FileReader(file);
			BufferedReader buf = new BufferedReader(in);
			System.out.println("Reading in file " + myWholeFileName);
			
			String line = buf.readLine();
while(line != null){

...

                        line = buf.readLine();
		        linecounter++;
}
```

Also ich lese die datei immer zeilenweise aus.
Was mache ich aber ab dem Punkt, ab dem ich zu den Binärdaten gelange?


----------



## redbomber (13. Feb 2009)

Also mir ist klar, dass ich mit dem FileReader Textdateien einlesen kann.

Für die Binärdaten brauche ich dann aber den FileInputStream.

Nur ich müsste ja an z.b. Zeile 9 meiner Datei von meinem FileReader zum FileInputStream wechseln.
Oder kann ich dem FileInputStream irgendwie informieren, ab welcher Zeil der datei er anfangen muss?


----------



## HannsW (13. Feb 2009)

redbomber hat gesagt.:
			
		

> Also mir ist klar, dass ich mit dem FileReader Textdateien einlesen kann.
> 
> Für die Binärdaten brauche ich dann aber den FileInputStream.
> 
> ...



Du musst mit dem FileInputStream arbeiten, und kommst nicht umhin, die Textzeichen zu casten:
	
	
	
	





```
BufferedInputStream fin = null;    // der geht schneller !
    int in = -1;
    String str = "";

    long skipOffset = 77125344;

    try {
        fin = new BufferedInputStream(new FileInputStream(inFileName));
    } catch (java.io.IOException io) {
        System.out.println("Kann Rep datei nicht öffnen");
        System.exit(1);
    }

  // dies dürfte Dir weiterhelfen ?? 
   try {
        fin.skip(skipOffset);
    } catch (java.io.IOException io) {
        System.exit(1);
}
```


----------



## redbomber (18. Feb 2009)

hey,
also ich hab das jetzt mal wie folgt probiert:

Während ich die ASCII Files auslese summiere ich die Anzahl der Bytes pro Line:

```
int skipBytes = 0;
BufferedReader buf = new BufferedReader(in);
String line = buf.readLine();
```

und dann zähle ich einfach am Ende die gelesenen Bytes zusammen:

```
byte[] ba = line.getBytes();
skipBytes += ba.length;
```

In meinem Binary Reader skippe ich dann diese Anzahl der Bytes
und kann danach die Double Werte auslesen:


```
FileInputStream file_input = new FileInputStream(myWholeFileName);
DataInputStream data_in = new DataInputStream(file_input);

data_in.skipBytes(...);

while (true) {
				try {
					d_data = data_in.readDouble();

				} catch (EOFException eof) {
					System.out.println("End of File");
					break;
				}
				
				data.add(d_data);
				
				System.out.println(d_data);
				counter++;
			}
			data_in.close();
```

Das ganze klappt aber noch nicht so ganz, es werden die falschen Werte ausgelesen, da das Leseraster der Bytes vermutlich verschoben ist.

Hab ich hier irgendwo einen Denkfehler drinne oder habt ihr vielleicht noch eine andere Idee?


----------



## HannsW (19. Feb 2009)

Nur ne Idee:
Könnt es sein, daß dir beim Addieren ein Byte pro Zeile verloren geht?
Nämlich das newLien in der Datei? 
Dann müsste dies klappen?

```
byte[] ba = line.getBytes();
skipBytes += ba.length + 1 ;
```


----------



## redbomber (12. Mrz 2009)

Also das habe ich jetzt auch ausprobiert, aber das klappt  noch immer nicht.
Es sind immer noch zu wenige Bytes die übersprungen werden.

Ich kann dies ja testen in dem ich einfach noch mehr bytes überspringe.
Irgend wann komme ich dann an die gewünschten Daten.

Hat vielleicht noch jemand eine Idee?


----------



## Spacerat (12. Mrz 2009)

Pauschal würde ich mal darauf tippen, das bei Verwendung von "readLine()", so manch ein String bereits Binärdaten enthält. Binärdaten dürfen nämlich ohne Linefeed enden. Da "readLine()" aber bis zum Ende einer Zeile, also bis zum Linefeed liest, wird eine folgende ASCII-Zeile natürlich überlesen. Hier hilft wohl nur ein Stream-Tokenizer, bei dem alle Nicht-ASCII-Zeichen als Tokens oder besser als Whitespace angesehen werden müssten, damit sie überlesen werden können. Ferner könnte es möglich sein, das ASCII-Daten nicht mit LF, sondern NULL-Terminiert enden. Eine solche Zeile landet mit "readLine()" sozusagen im Hades.


----------



## redbomber (20. Mrz 2009)

Also meine Files besitzen alle dieselbe Anzahl an "ASCII Zeilen", worin jedoch etwas unterschiedliches steht.

Nun habe ich bemerkt, dass die ermittelte Anzahl der zu überspringenden Bytes ja immer zu klein ist.
Bei allen Files muss ich DENSELBEN Wert hinzu addieren und dann passt das ganze.

Da die Zeilenanzahl der Kommentare also gleich ist, wird das wie du gesagt hast etwas mit den readLines() zu tun haben.


--------------------

jo, hätte nicht gedacht das dies so kompliziert ist 

mal eine Frage zu einem anderem Ansatz.
Ich dachte daran das File komplett in Bytes einzulesen. Gibt es die Möglichkeit an einem Byte zu erkennen, ob es sich dabei um ein NewLine Zeichen handelt?
Weil dann könnte ich einfach z.b. das 7te Newlin zeichen suchen, danach weiss ich dann dass meine Daten anfangen.


----------



## Spacerat (20. Mrz 2009)

Hatte ich in meinem Beitrag schon erwähnt -> "Stream-Tokenizer"...


----------



## redbomber (27. Mrz 2009)

ja aber welche Information soll ich denn von dem StringTokenizer erhalten?
Ich kann ja nicht die bytes für jedes Token auslesen oder so.

Also ich versteh nur nicht wie ich den String Tokenizer hier anwenden muss, damit ich etwas über die Anzahl der zu überspringenden Bytes erfahre.


----------



## Ebenius (27. Mrz 2009)

Lies nochmal! Spacerat spricht von einem Str*eam*Tokenizer.

Ebenius


----------



## Spacerat (27. Mrz 2009)

... genau... StreamTokenizer... nicht zu verwechseln mit StringTokenizer 
[highlight=java]package extended.stream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class ExtendedStreamTokenizer
extends StreamTokenizer
{
 public static final IOException UNEXPECTED_EOF = new IOException("unexpected end of file");
 public static final IOException UNEXPECTED_OPEN = new IOException("unexpected open char");
 public static final IOException UNEXPECTED_CLOSE = new IOException("unexpected close char");
 public static final int
  TT_CLOSE = -5,
  TT_OPEN = -6,
  TT_INVALID = -7,
  TT_DOUBLEQUOTE = '"',
  TT_SINGLEQUOTE = '\'';
 private final BufferedInputStream in;
 private int open = '{', close = '}', markedType;
 private String markedString;
 private double markedNumber;
 public ExtendedStreamTokenizer(BufferedInputStream in)
 {
  super(new InputStreamReader(in));
  this.in = in;
 }
 public void whitespaceChar(int token)
 {
  whitespaceChars(token, token);
 }
 public void parseNumbers(boolean sw)
 {
  if(sw) {
   super.parseNumbers();
  } else {
   ordinaryChars('0', '9');
   ordinaryChar('.');
   ordinaryChar('-');
   wordChars('0', '9');
   wordChar('.');
   wordChar('-');
  }
 }
 public void wordChar(int token)
 {
  wordChars(token, token);
 }
 public void openChar(int token)
 {
  open = token & 0xFF;
 }
 public void closeChar(int token)
 {
  close = token & 0xFF;
 }
 public int nextToken()
 throws IOException {
  super.nextToken();
  if(ttype == open) ttype = TT_OPEN;
  if(ttype == close) ttype = TT_CLOSE;
  return ttype;
 }
 public void nextLine()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_EOL);
 }
 public void nextWord()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_WORD);
 }
 public void nextNumber()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_NUMBER);
 }
 public void nextClose()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_CLOSE);
 }
 public void nextOpen()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_OPEN);
 }
 public void nextQuotedString()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_DOUBLEQUOTE && ttype != TT_SINGLEQUOTE);
 }
 public void nextSingleQuotedString()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_SINGLEQUOTE);
 }
 public void nextDoubleQuotedString()
 throws IOException
 {
  do {
   if(ttype == TT_EOF) throw UNEXPECTED_EOF;
   nextToken();
  } while(ttype != TT_DOUBLEQUOTE);
 }
 public synchronized void mark(int readlimit)
 {
  in.mark(readlimit);
  markedType = ttype;
  markedString = sval;
  markedNumber = nval;
 }
 public synchronized void reset()
 throws IOException
 {
  in.reset();
  ttype = markedType;
  sval = markedString;
  nval = markedNumber;
 }
 public synchronized int available()
 throws IOException
 {
  return in.available();
 }
}[/highlight]Dieser Code dürfte der Grund dafür sein, warum ich den StringTokenizer gar nicht mehr brauche. Zeilen zählen, Wörter zählen, Diverse String-Typen (SingleQuoted, DoubleQuoted, 0-Terminiert) lesen, im Prinzip allses was ein entsprechend konfigurierter StreamTokenizer auch kann. Zusätzlich kann an jeder beliebigen der Stream markiert werden, und später an die Stelle zurück gesprungen werden. Deswegen ist dafür auch ein BufferedInputstream nötig. Hier klemmts allerdings noch bei "LINENO", aber man arbeitet dran. Vllt. hilft der ja weiter. Ist aber (wie der grösste teil meines Quellcodes) nicht Dokumentiert.


----------



## Spacerat (27. Mrz 2009)

Ok... Doppelpost...
Hab' glaub' ich genug am Code oben rumeditiert... Ich frage mich, wieso ständig die Leerzeichen, Tabs und Leerzeilen bei Verwendung des Highlight-Tags verschwinden... Ist das normal, oder mache ich was falsch?


----------



## Ebenius (27. Mrz 2009)

[off topic] Keine Ahnung, ich kann das nicht nachvollziehen. In der ersten Zeile fehlen immer alle Leading Blanks. Benutzt Du den WYSIWYG-Editor? Mit dem Standard-Editor hab ich die Probleme nicht. Ach ja: In meinem Code hab ich nie TABs, sondern immer SPCs drin; keine Ahnung was mit TABs passiert. Allerdings editier ich ziemlich viel fremde Posts wg. fehlender Formatierung und da ist mir sowas auch noch nicht untergekommen.

Ebenius


----------

