Hallo,
ich bin auf der Suche nach einem komischen Bug und habe dabei ein merkwürdiges Verhalten beobachtet.
Also mein Bug war Folgendes:
Ich lese mit einem Java-Programm einzeln Dateien ein. Der Inhalt wird nach bestimmten Kriterien gefiltert und der Rest wird in eine neue Datei geschrieben. Nun kommt mein Bug ins Spiel. Dieses Verhalten tritt bei allen Dateien, außer der ersten auf.
Es werden die letzten sieben Zeilen der vorigen Datei an den Anfang der folgenden Datei geschrieben. Ich benutze in meinem Programm eine Queue, als Datenstrucktur eine ArrayList. Diese ArrayList soll maximal 30 Elemente lang werden. Wird ein Element an eine 30-elementige Queue gehangen, wird das erste Element gelöscht.
Kann es sein, dass eine ArrayList initial von der JVM eine Länge von sieben bekommt?
Aufgerufen wird diese Klasse in einem Thread
Vielleicht sieht ja jemand meinen Bug. Ich habe ihn nicht gefunden bisher.
Dann zum Verhalten der IDE. Wenn ich mein bugbehaftetes Programm in der IDE ablaufen lasse, dann gibt es den Fehler nicht. Alle Zeilen sind in den Dateien, wo sie hin sollen. Ich benutze Eclipse 3.1 auf Java 1.5.0 Update 6.
Ciao, micbur
ich bin auf der Suche nach einem komischen Bug und habe dabei ein merkwürdiges Verhalten beobachtet.
Also mein Bug war Folgendes:
Ich lese mit einem Java-Programm einzeln Dateien ein. Der Inhalt wird nach bestimmten Kriterien gefiltert und der Rest wird in eine neue Datei geschrieben. Nun kommt mein Bug ins Spiel. Dieses Verhalten tritt bei allen Dateien, außer der ersten auf.
Es werden die letzten sieben Zeilen der vorigen Datei an den Anfang der folgenden Datei geschrieben. Ich benutze in meinem Programm eine Queue, als Datenstrucktur eine ArrayList. Diese ArrayList soll maximal 30 Elemente lang werden. Wird ein Element an eine 30-elementige Queue gehangen, wird das erste Element gelöscht.
Kann es sein, dass eine ArrayList initial von der JVM eine Länge von sieben bekommt?
Code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.Pattern;
public class LogLineQueue {
private int queuelength = 30;
private ArrayList queue = null;
private ArrayList garbage = null;
public LogLineQueue() {
this.queue = new ArrayList(this.queuelength);
this.garbage = new ArrayList(0);
}
public LogLineQueue(int length) {
this.queuelength = length;
this.queue = new ArrayList(this.queuelength);
this.garbage = new ArrayList(0);
}
public int getQueuelength() {
return queuelength;
}
public void setQueuelength(int queuelength) {
this.queuelength = queuelength;
}
/**
* enqueue() schiebt Elemente wieder raus, wenn
* Elemente hinzugefügt werden!
* Vorne anfügen, hinten rausfallen. FIFO!
* */
public LogLine[] enqueue(LogLine obj) {
ArrayList output_list = new ArrayList(0);
LogLine[] out = null;
while (this.queue.size() >= this.queuelength) {
output_list.add(this.queue.get(0));
this.queue.remove(0);
}
// conditions prüfen
// hier werden die einzelnen Zeilen auf this.queue oder this.garbage verteilt
// es wird this.queue.add(Object) und this.garbage.add(Object) benutzt
// Work-A-Round, als Array von der ArrayList zurückbekommen hat nicht funktioniert, wird mit O(n) Aufwand selbst gemacht.
out = new LogLine[output_list.size()];
for (int i = 0; i < output_list.size(); i++) {
out[i] = (LogLine) output_list.get(i);
}
for (int i = 0; i < output_list.size(); i++ ) {
output_list.remove(0);
}
return out;
}
public boolean contains(LogLine arg) {
LogLine current = null;
Iterator i = this.queue.iterator();
while (i.hasNext()) {
current = (LogLine) i.next();
if (current.compareTo(arg) == 0) {
return true;
}
}
return false;
}
public LogLine[] getGarbage() {
LogLine[] out = new LogLine[garbage.size()];
for (int i = 0; i < garbage.size(); i++) {
out[i] = (LogLine) this.garbage.get(i);
}
for (int i = 0; i < this.garbage.size(); i++) {
this.garbage.remove(0);
}
this.garbage = null;
this.garbage = new ArrayList(0);
return out;
}
public LogLine[] empty() {
LogLine[] out = new LogLine[this.queue.size()];
for (int i = 0; i < this.queue.size(); i++) {
out[i] = (LogLine) this.queue.remove(0);
}
for (int i = 0; i < this.queue.size(); i++) {
this.queue.remove(0);
}
this.queue = null;
this.queue = new ArrayList(0);
return out;
}
}
Aufgerufen wird diese Klasse in einem Thread
Code:
public void run() {
BufferedReader readfilein = null;
BufferedWriter new_logfile = null;
BufferedWriter garbagefile = null;
String one_line = null;
LogLine[] loglines_arr = null;
StringBuffer buffer = new StringBuffer();
LogLine current = null;
int processed = 0;
int filtered = 0;
try {
readfilein = new BufferedReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(this.logfilename))));
new_logfile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(this.logfilename + ".mod")));
one_line = readfilein.readLine();
while(one_line != null) {
current = new LogLine(one_line);
// work-a-round für Logzeilen, die kürzer als 14 Spalten sind, z.B. Headerzeilen der Logfiles
/*
public class LogLine implements Comparable {
private String payload = null;
private String timestamp = null;
...
}
*/
if (current.getPayload() == null) {
current.setTimestamp("");
current.setPayload(one_line);
}
// die erzeugte LogLine zur Queue hinzufügen
// Rückgabewert der Queue ist der Überhang der Queue.
// Regel: Wird das 31te Element an eine 30-stellige Queue übergeben, fällt das erste Element raus.
loglines_arr = this.window.enqueue(current);
// Queue zurück in das neue Log schreiben
for (int i = 0; i < loglines_arr.length; i++ ) {
if (loglines_arr[i] != null) {
processed++;
buffer.append(loglines_arr[i].getLogline() + System.getProperty("line.separator", "\n\r"));
}
}
// da zuerst ein Buffer gefüllt wird, muss dieser immer zurück in Dateien geschrieben werden.
// Der Buffer soll eine bestimmte Mindestgröße erreichen, bevor er geschrieben wird.
if (buffer.length() > this.writeBufferSize) {
new_logfile.write(buffer.toString());
buffer.delete(0, buffer.length());
new_logfile.flush();
}
new_logfile.flush();
// erneut eine Zeile einlesen, Scheife nochmal durchlaufen
one_line = readfilein.readLine();
}
new_logfile.write(buffer.toString());
buffer.delete(0, buffer.length());
// die letzten LogLines aus der Queue holen & in den Buffer schrieben
loglines_arr = this.window.empty();
for (int i = 0; i < loglines_arr.length; i++ ) {
if (loglines_arr[i] != null) {
processed++;
buffer.append(loglines_arr[i].getLogline() + System.getProperty("line.separator", "\n\r"));
}
}
new_logfile.flush();
new_logfile.write(buffer.toString());
buffer.delete(0, buffer.length());
buffer = new StringBuffer("");
buffer = null;
new_logfile.flush();
new_logfile.close();
this.filtered_counter = filtered;
this.processed_counter = processed;
}
catch (IOException e) {
e.printStackTrace();
}
}
Vielleicht sieht ja jemand meinen Bug. Ich habe ihn nicht gefunden bisher.
Dann zum Verhalten der IDE. Wenn ich mein bugbehaftetes Programm in der IDE ablaufen lasse, dann gibt es den Fehler nicht. Alle Zeilen sind in den Dateien, wo sie hin sollen. Ich benutze Eclipse 3.1 auf Java 1.5.0 Update 6.
Ciao, micbur