Textdatei auf gewünschte Anzahl der Zeilen kürzen

xote

Mitglied
Hallo allerseits,

Ich schreibe gerade eine eigene Logging-Klasse, dabei versuche ich gerade eine log-Datei (Textdatei) auf die gewünschte Anzahl von Zeilen zu kürzen. Eine funktionierende Lösung habe ich wie es aussieht schon gefunden, allerdings ist diese Lösung auch enorm langsam.

Im Grunde genommen mache ich das im Moment so: vom log-file wird die Zeilenanzahl ermittelt, wenn die höher ist als die gewünschte Zeilenanzahl wird das log-file getrimmt. Dazu werden alle Zeilen wieder in eine Liste gelesen, diese dann entsprechend gekürzt, dann das alte log-file gelöscht und neu geschrieben.

Wie gesagt läuft mir das irgendwie viel zu langsam. Ich hätte mir auch schon überlegt, den Inhalt der Liste ständig im Speicher zu halten aber das erscheint mir dann doch noch verschwenderischer.

Hat vielleicht irgendwer einen besseren Ansatz? Oder gibt es Verbesserungen am Code selbst? Wo verschenke ich vielleicht viel Laufzeit?

Danke im Voraus...

Java:
	private void trimLogFileToMaximumLines(File textFile, int maximumLines, boolean trimAtBegin) {
		int actualLogFileLineCount = countLinesInTextFile(logFile);
		if(actualLogFileLineCount > maximumLines) {
			ArrayList<String> logFileLines = new ArrayList<String>();
			try {
				FileReader fr = new FileReader(logFile);
				LineNumberReader ln = new LineNumberReader(fr);
				try {
					boolean linesLeft = true;
					while(linesLeft) {
						String line = ln.readLine();
						if(line == null) {
							linesLeft = false;
						} else {
							logFileLines.add(line);
						}
					}
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
			} catch (FileNotFoundException fnfe) {
				fnfe.printStackTrace();
			}
			logFile.delete();
			while(logFileLines.size() > maximumLines) {
				if(trimAtBegin) {
					logFileLines.remove(0);
				} else {
					logFileLines.remove(logFileLines.size()-1);
				}
			}
			for (String line : logFileLines) {
				appendLogEntryToLogFile(line);
			}
		}
	}
Java:
	public int countLinesInTextFile(File logFile) {
		int count = 0;
		if(logFile.exists()) {
			try {
				FileReader fr = new FileReader(logFile);
				LineNumberReader ln = new LineNumberReader(fr);
				try {
					while(ln.readLine() != null) {
						count++;
					}
					ln.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		return count;
	}
Java:
	private void appendLogEntryToLogFile(String composedLogMessage) {
		boolean append = true;
		FileWriter fw = null;
		try {
			fw = new FileWriter(logFile,append);
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		try {
			fw.write(composedLogMessage + System.getProperty("line.separator"));
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		try {
			fw.close();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
	}
 
Java:
while(logFileLines.size() > maximumLines) {
    // ...
    logFileLines.remove(logFileLines.size()-1);
}
Bin mir zwar nicht sicher, aber hier könnte´s u.U. krachen, da du zwar immer schön Zeilen löschst, aber die Größe der Liste sich gar nicht ändert... hab ich aber nicht überprüft, ist nur ´ne Vermutung.

Nichtsdestotrotz noch ein kleiner Tipp: wenn du dreimal eine IOException fangen und auf die gleiche Art und Weise verarbeiten willst (in deinem Fall e.()), dann kannst du die auch alle zusammenschmeißen, da wird´s etwas übersichtlicher.
Java:
 boolean append = true;
        FileWriter fw = null;
        try {
            fw = new FileWriter(logFile,append);
            fw.write(composedLogMessage + System.getProperty("line.separator"));
            fw.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
Selbes gilt für dieses Konstrukt hier:
Java:
try {
                FileReader fr = new FileReader(logFile);
                LineNumberReader ln = new LineNumberReader(fr);
                try {
                    boolean linesLeft = true;
                    while(linesLeft) {
                        String line = ln.readLine();
                        if(line == null) {
                            linesLeft = false;
                        } else {
                            logFileLines.add(line);
                        }
                    }
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            } catch (FileNotFoundException fnfe) {
                fnfe.printStackTrace();
            }
Ordne das mal alles ein bisschen, sieht ja kein Mensch mehr durch...
 
^^ Erstens das und zweitens, warum die Datei beim Zählen, Kürzen und anschliessendem Verwenden immer wieder neu Laden? Das dürfte so eine Art "Log-Daily" werden, blos halt mit fester Zeilenzahl, statt mit einem festen Zeitraum. Drittens:
Java:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;


public class SimpleLogDemo
{
	public enum MsgType {
		INFO(0),
		WARN(1),
		FAIL(2),
		;

		private final int level;

		private MsgType(int level)
		{
			this.level = level;
		}
	}

	private static final int MAX_ENTRYS = 20;

	private final String logFile;
	private FileWriter log;
	private MsgType type = MsgType.INFO;
	private int entrys;

	private SimpleLogDemo(String logFile)
	{
		this.logFile = logFile;
		try {
			File file = new File(logFile);
			log = new FileWriter(file, file.exists());
		} catch(IOException e) {
			// shouldn't happen
		}
	}

	public void setLevel(MsgType type)
	{
		if(type == null) {
			throw new NullPointerException("type may not be null");
		}
		this.type = type;
	}

	public void log(String msg, MsgType type)
	throws IOException
	{
		msg = "["+ type.toString() + "] " + msg + "\n";
		if(type.level >= this.type.level) {
			log.write(msg);
			entrys++;
		}
		if(entrys == MAX_ENTRYS) {
			log.close();
			File file = new File(logFile);
			File renamed = new File(logFile + "." + System.currentTimeMillis());
			file.renameTo(renamed);
			log = new FileWriter(file, false);
		}
	}

	public void splitOldLogs(File logFile)
	throws IOException
	{
		BufferedReader reader = new BufferedReader(new FileReader(logFile));
		String line;
		if((line = reader.readLine()) != null) {
			log("copy of " + line, MsgType.INFO);
		}
		reader.close();
	}
}
 

Zurück
Oben