RandomAccessFile springt zum Ende

Status
Nicht offen für weitere Antworten.

Rock Lobster

Bekanntes Mitglied
Servus,

seit heut hab ich ein sehr seltsames Problem. Bisher haben RandomAccessFiles immer perfekt funktioniert, doch seit heute springt der FilePointer von allein irgendwann ganz ans Ende. Ich verstehe aber nicht warum, und ich habe auch die Stellen, an denen mein Programm den FilePointer selbst beeinflußt, mit Log-Ausgaben versehen. Dabei kam raus, daß mein Programm nicht schuld ist, sondern der Pointer von ganz allein plötzlich nach hinten springt.

Das einzige, was mir noch aufgefallen ist, ist daß der Zeitpunkt beeinflußbar ist. Und zwar lese ich in einer Schleife immer wieder aus der Datei - wenn ich die Größe des Buffers reduziere, dann tritt der Effekt auch schneller auf. Ich gebe mir in der Schleife dauernd den FilePointer aus, und egal, wo ich mich in der Datei befinde, nach ein paar Durchläufen springt der Pointer wie gesagt exakt ans Ende.

Ich versteh das nicht, vor allem hat es bisher immer funktioniert, und erst seit heute zickt das Programm rum (und die Datei, die gelesen wird, ist übrigens auch noch dieselbe wie schon immer).

Woran kann das liegen?


EDIT: Ich hab noch einen weiteren Beweis, daß es nicht an meinem Programm liegt - und zwar abstrahiere ich den Datei-Input über eine eigene Klasse, wodurch ich wahlweise mit einem RandomAccessFile arbeiten kann, oder mit einer Datei, die komplett in den Speicher gelesen wurde. Das Programm verhält sich also in beiden Fällen gleich, und wenn ich aus dem Speicher rauslese, tritt der Effekt nicht auf. Wenn ich wieder auf den Dateizugriff umstelle dagegen schon. Und auch dieser Mechanismus ist seit 'nem halben Jahr etwa der gleiche und wurde auch nicht verändert.
 

Rock Lobster

Bekanntes Mitglied
Hab's jetzt nochmal isoliert getestet mit einem kleinen Testprogramm, da lief es jedoch... werde wohl den Code nochmal genauer untersuchen müssen :/
 

Rock Lobster

Bekanntes Mitglied
Ich hab's immer noch nicht... hat keiner eine Idee, woran es liegen könnte? Ich hab alles überprüft, es gibt niemanden, der irgendwie an der Datei rumfummelt.

Ich hab die folgenden Ausgaben gemacht:

1. FilePointer vor dem Aufruf der Lesefunktion
2. FilePointer unmittelbar vor dem Lesen
3. FilePointer unmittelbar nach dem Lesen
4. FilePointer nach dem Aufruf der Lesefunktion

Manchmal ist der Pointer bei 1. noch richtig und bei 2. falsch, manchmal erst bei 4., interessanterweise sind 2. und 3. allerdings immer zueinander konsistent.
Manchmal sind auch alle insgesamt konsistent, sprich, der FilePointer ändert sich irgendwann zwischen 4. und dem erneuten Aufkommen von 1.

Ich hab alle Threads abgeschaltet, die irgendwie überflüssig sind, sodaß es nur noch 2 Threads gab, der MainThread, der mit der Datei nix am Hut hat, und der Thread, der aus der Datei liest. Trotzdem ändert sich der FilePointer irgendwann. Nicht immer zum gleichen Zeitpunkt, mal sehr früh, mal erst spät. Absolut unvorhersehbar, was die Zeit angeht, aber auftreten tut es auf jeden Fall.

Woran kann das nur liegen?!
 
T

tuxedo

Gast
Wenn es mit deinem kleinen Tetsprogramm keine Probleme gibt, dann ist dein eigentliches Programm ja an der misere Schuld. Und da die Chance dass jemand dieses Phänomen schonmal hatte vermutlich nicht sehr hoch ist (ist wirklich ein äußerst seltsames phänomen), wäre es vielleicht nicht schlecht ein wenig Code zu sehen, oder?
 

Rock Lobster

Bekanntes Mitglied
Naja ich bin den Code grad mit einem Kollegen durchgegangen, und wir haben beide nix gefunden. Außerdem ist die Sache sehr komplex, aber ich versuche mal, die wichtigsten Teile zu posten.

Das ist der Code, der in einer Schleife immer wieder aufgerufen wird:
Code:
	public int readNextData(float[] buffer)
	{
		try
		{
			int numSamples = 0;
			int fill = 0;
			
			float[] temp = null;
			
			AudioObject audio = null;
			long time = this.currentTime;
			
			
			while(numSamples < buffer.length)
			{
				audio = getAudio(time);
				
				if (audio != currentAudio || currentAudio.isSilent() || currentAudioTime != getPrevTime(time))
				{
					currentAudio = audio;
					currentAudio.setTime(time - getPrevTime(time));
					currentAudioTime = getPrevTime(time);
				}

				if (currentAudio.isSilent())
					fill = (int)((float)(getNextTime(time) - time) / 1000 * 44100);
				else
					fill = buffer.length - numSamples;
				
				if (time >= this.getEndOfTrack())
				{
					currentAudio = AudioObject.silentObj;
					fill = buffer.length - numSamples;
					
					sendMessage(new TrackMessage(TrackMessage.Type.END_OF_TRACK, this));
				}
				
				if (fill > buffer.length - numSamples)
					fill = buffer.length - numSamples;
				
				temp = new float[fill];
				int readSamples = currentAudio.readNextData(temp);
				
				if (readSamples > 0)
				{
					System.arraycopy(temp, 0, buffer, numSamples, readSamples);
					numSamples += readSamples;
					System.out.println("+++");
				}
				else
				{
					//currentAudio = AudioObject.silentObj;
					//break;
				}
				
				time = this.currentTime + (int)((float)numSamples / 44100 * 1000);
			}

			this.currentTime += ((float)buffer.length / 44100 * 1000);
			
			return numSamples;
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		return 0;
	}

Dort seht ihr einen Aufruf: int readSamples = currentAudio.readNextData(temp);

Dazu hier die passenden Methoden:
Code:
	public int readNextData(float[] buffer)
	throws IOException, BadAudioFormatException
	{
		if (silence)
		{
			for(int i=0; i<buffer.length; i++)
				buffer[i] = 0;
			
			silencePos += getFormat().bytesToTime(buffer.length);
			
			return buffer.length;
		}
		
		switch(channel)
		{
		case MONO_LEFT:
			return readOneChannel(buffer, CHANNEL_OFFSET_LEFT);
			
		case MONO_RIGHT:
			return readOneChannel(buffer, CHANNEL_OFFSET_RIGHT);
		}
		
		return 0;
	}
	
	
	private int readOneChannel(float[] buffer, int channelOffset)
	throws IOException, BadAudioFormatException
	{
		float timeFrom = stream.getPositionf();
		float[] floats = readToFloat(buffer.length * getFormat().getFrameSize());
		float timeTo = stream.getPositionf();

		int numSamples = floats.length;
		int channels = getFormat().getChannels();
		
		for(int i=channelOffset, k=0; i<numSamples; i+=channels, k++)
			buffer[k] = floats[i];
		
		for(Range c : cuts)
		{
			if (c.from <= timeTo && c.to >= timeFrom)
			{
				int start	= getSampleNumber(c.from - timeFrom);
				int end		= getSampleNumber(c.to - timeFrom);

				for(int i=start; i<end; i++)
					if (i < buffer.length && i < numSamples)
						buffer[i] = silenceByte;
					else
						break;
			}
		}
		
		return numSamples / getFormat().getChannels();
	}
	
	
	private float[] readToFloat(int len)
	throws IOException, BadAudioFormatException
	{
		byte[] bytes = new byte[len];
		int numBytes = stream.read(bytes, 0, len);
		
		if (numBytes < 0)
			return new float[0];
		
		if (numBytes < len)
		{
			byte[] temp = new byte[numBytes];
			System.arraycopy(bytes, 0, temp, 0, numBytes);
			bytes = temp;
		}
		
		return AudioTools.getFloatArray(bytes, getFormat().getSampleSizeInBits());
	}

Diese wiederum besitzen ein Objekt namens "stream", welches letztendlich nur eine Art Wrapper ist auf das RandomAccessFile. Aber alles was darunter liegt wurde ca. ein halbes Jahr lang nicht angefaßt und hat bis vorgestern noch perfekt funktioniert.

Wie gesagt, ich hab den Code schon bis zum Erbrechen analysiert, aber vergebens.
 

Rock Lobster

Bekanntes Mitglied
Ach ja, die oben angesprochenen 4 Ausgaben waren wie folgt verteilt:

1. oberes Beispiel, Zeile 40
2. unteres Beispiel, vor Zeile 64
3. unteres Beispiel, nach Zeile 64
4. oberes Beispiel, Zeile 43
 

Rock Lobster

Bekanntes Mitglied
Spaßeshalber hab ich mal noch im ersten Beispiel unterhalb von Zeile 23 den folgenden Code eingefügt:

Code:
				if (! currentAudio.isSilent())
				{
					int cnt = 1;
					
					while(cnt > 0)
					{
						cnt = currentAudio.readNextData(buffer);
						System.out.println(currentAudio.getPosition() + "\t\t\t" + cnt);
					}
					
					System.exit(666);
				}

Auch hier tritt das Phänomen auf, der FilePointer wird dauernd korrekt angezeigt und urplötzlich steht er am Ende (und das Programm beendet sich ebenfalls).
EDIT: Das zeigt eigentlich auch, daß der Code im ersten Beispiel korrekt ist, bzw. es nicht damit zu tun hat.
Ach ja, das gleiche hab ich auch in meinem externen Testprogramm gemacht. Aber dort hat es, wie gesagt, funktioniert...
 
T

tuxedo

Gast
Hmm, wie wird denn die Position bestimmt?

Ich hatte in meiner Diplomarbeit auch mit Audiostreams zu tun. Und da hatte ich das "Problem" dass ich ein readFully() implementieren musste weil ein einfaches read() das übergebene byte[] nicht immer ganz gefüllt hat. Bei mir hat das durch den AudioCodec zu "StreamCorruptedException"s geführt.

Aber das passt ja nicht zu deinem Phänomen. Bei dir würde er ja zu viel lesen damit er vorzeitig beim EOF ankommt.

Hmm.

- Alex
 

Rock Lobster

Bekanntes Mitglied
Ich hab grad nochmal mit jemanden getestet und hab bemerkt, daß im Hintergrund dauernd nach der totalen Länge des Tracks gefragt wird.

Jetzt ist es natürlich möglich, daß diese Länge ermittelt wird, indem das File kurzzeitig ans Ende springt um den FilePointer zu lesen und dann wieder an die ursprüngliche Position. Möglicherweise lese ich dann genau in solch einem Moment - das würde auch erklären, warum es immer zu anderen Zeiten auftritt.

Ich werd's mal kurz weiter untersuchen und dann Bescheid geben :)
 
T

tuxedo

Gast
Ja, das hört sich so an, als obs das sein könnte. Aber wieso lässt du nicht einmal am Anfang die totale Länge abfragen und verwendest dann im Verlauf ne Variable dafür?

- Alex
 

Rock Lobster

Bekanntes Mitglied
HEUREKA!

Es war tatsächlich genau das: getLength() auf ein RandomAccessFile scheint wohl den FilePointer kurzzeitig ans Ende zu setzen und dann wieder zurück an die letzte Position. Wenn das nun multithreadingmäßig geschieht und ein anderer Thread genau in diesem Moment lesen will, ist die Position im Arsch.

Argh, auf sowas muß man erstmal kommen... seit heut morgen mach ich da schon dran rum ;)
 

Rock Lobster

Bekanntes Mitglied
@ Alex: Tja gute Frage... gut möglich, daß ich damals einfach nicht drüber nachgedacht hab, bzw. die Länge für "änderbar" hielt (wer weiß das schon). Hab's jetzt aber über eine Variable gemacht ;)
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
S RandomAccessFile durch bytearrayinputstream ersetzen Allgemeine Java-Themen 4
A RandomAccessFile.read(byte[] b) Allgemeine Java-Themen 9
A RandomAccessFile - "insert" implementieren? Allgemeine Java-Themen 4
Iron Monkey RandomAccessFile - Bestimmte Filesize begrenzen Allgemeine Java-Themen 4
H RandomAccessFile - Zeile finden Allgemeine Java-Themen 5
C RandomAccessFile aus Jar Allgemeine Java-Themen 7
T Mit Applet per RandomAccessFile Datei öffnen Allgemeine Java-Themen 3
reibi RandomAccessFile Puffer schreiben Allgemeine Java-Themen 2
J RandomAccessFile readLine(); Allgemeine Java-Themen 5
P Nochmal RandomAccessFile Allgemeine Java-Themen 6
N RandomAccessFile überschreibt Inhalt Allgemeine Java-Themen 3
A RandomAccessFile - Bytes vom Anfang der Datei löschen Allgemeine Java-Themen 32
B Probleme mit RandomAccessFile Allgemeine Java-Themen 3
R Knacken bei RandomAccessFile Allgemeine Java-Themen 5
K RandomAccessFile und readUTF/writeUTF Allgemeine Java-Themen 4
T RandomAccessFile im .jar Allgemeine Java-Themen 2
M RandomAccessFile Allgemeine Java-Themen 10
Robertop BigDecimal ergänzt unnötige 0 am Ende Allgemeine Java-Themen 6
Joker4632 Klassen Buffered Reader liest die Leerzeichen am Zeilen Ende nicht mehr Allgemeine Java-Themen 2
N Das Ende von bestimmten zeilen in text datei ändern und speichern Allgemeine Java-Themen 3
OnDemand String splitten (mit Anfang und Ende) Allgemeine Java-Themen 11
A Datentypen Long.valueOf liefert kein "L" am Ende Allgemeine Java-Themen 3
M String shuffeln, Anfang und Ende aber bleiben gleich Allgemeine Java-Themen 15
M Methoden Methode führt Ende vor dem Anfang aus Allgemeine Java-Themen 7
S Threads Ende sämtlicher Threads abwarten Allgemeine Java-Themen 6
T Problem mit gzip Stream und Ende der Datei Allgemeine Java-Themen 2
T Array Sortieren (null Werte ans Ende) Allgemeine Java-Themen 2
M itext Leerzeichen am ende unterstreichen Allgemeine Java-Themen 4
O Wie kann ich das Ende eines Threads melden? Allgemeine Java-Themen 7
F externes Programm beginnt erst nach dem ende des mainprogrammes Allgemeine Java-Themen 3
E Text ans Ende einer Textdatei anfügen Allgemeine Java-Themen 2
D Java Thread, Bild wird nur am Ende gezeichnet Allgemeine Java-Themen 5
L Warten bei mehreren Threads, bis Ende erreicht ist Allgemeine Java-Themen 2
J Listener für Ende eines Threads gesucht... Allgemeine Java-Themen 5
E beim Ende der main() das Programm nicht beenden Allgemeine Java-Themen 3
D Ans Ende einer txt Datei schreiben Allgemeine Java-Themen 13
K Scanner.hasNext findet kein Ende Allgemeine Java-Themen 6
B ObjectInputStream - Wann ist Ende erreicht? Allgemeine Java-Themen 10
S MediaTracker nutzen um festzustellen ob schreibvorgang ende. Allgemeine Java-Themen 5
D das Ende eines Threads Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben