Input/Output Große Dateien schnell Speichern/auslesen

  • Themenstarter Themenstarter .Niklas.
  • Beginndatum Beginndatum
N

.Niklas.

Gast
Hallo,
Ich arbeite zurzeit an einem Plugin für Minecraft und ich möchte Blöcke schützen, mein problem ist das es schon bei 10 tausend gespeicherten blöcken anfängt bei einem Server reload etwa 5-6 sekunden zu hacken

Ich lese die .yml aus mit:
Code:
	public String fileGetContent()
    {
        String buffer = "";
        String line = "";
        
        try
        {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(myFile)));
            while((line = br.readLine()) != null) 
                buffer = (new StringBuilder(String.valueOf(buffer))).append(line = (new StringBuilder(String.valueOf(line))).append("\n").toString()).toString();
            br.close();
        }
        catch(Exception e)
        {
            System.out.println("[MineBuilder] A file is missing, please reload the server when this error is still there contact me");
        }
        return buffer;
    }

Und wird dann hier verarbeitet:
Code:
	private ArrayList<String> saveBlock = new ArrayList<String>();	

public void readBlockSaveFile()
	{
		configer saveBlockYml = new configer("plugins/MineBuilder","plugins/MineBuilder/SavedBlocks.yml");
		String[] saveBlockSplit = saveBlockYml.fileGetContent().split("\n");
		Boolean add = false;
		for(String addSave : saveBlockSplit)
		{
			if(add == true)
			{
				saveBlock.add(addSave);
			}
			if(addSave.contains("Latest Block at:"))
			{
				add = true;
				String[] numberSplit = addSave.split(":");
				amountOfSavedBlocks = Integer.parseInt(numberSplit[1]);
			}
		}
	}
Bei " String[] saveBlockSplit = saveBlockYml.fileGetContent().split("\n"); " dauert es sehr lange 🙁
(liegt nicht am split , ich habs getestet)


Und dann habe ich noch ein problem beim trennen der ArrayList gibts da eine Methode die schneller ist als

Code:
	public void writeBlockSaveFile()
	{
	    ArrayList<String> saveBlockCopy = new ArrayList<String>();
	    saveBlockCopy.addAll(saveBlock);  //Mit es keine errors gibt falls saveBlock sich verändert
		configer saveBlockYml = new configer("plugins/MineBuilder","plugins/MineBuilder/SavedBlocks.yml"); 
		String writeToFile = "Latest Block at:"+amountOfSavedBlocks+freizeile; //Speichert die array list in einen string
//Hier hackt es 
		for(String savePlaceBlock : saveBlockCopy)
		{
				writeToFile += savePlaceBlock+freizeile;

		}
//Speichert es in einem file 
		saveBlockYml.writeFile(writeToFile);
	}

Wie mache ich es das er die Datei schneller ausliest und Die ArrayList "blockSave" schneller speichern kann 🙂?

Mfg Niklas
 
Da merkt man irgendwie wieder dieses "wenn Kiddies wegen Minecraft anfangen mit Java zu spielen".

Nichts gegen dich, aber dieser MIST zeigt eindeutig das du da ne Menge ausm Netz zusammengeklickt hast und dich scheinbar mit Java überhaupt nicht auskennst.

Als Tipp gebe ich dir nur : anstatt EINEN String zu returnen der dann wieder gesplitet wird gib lieber gleich die List<String> zurück. Denn alleine deine "buffer=..." Zeile frisst unmengen an RAM und CPU. Und das gleiche geht dann beim spli() noch mal rückwärts. Das das extrem unperformant ist weis eigentlich jeder Java-Anfänger der sich schon mal mit Listen und dem Thema "Einlesen von Files" befasst hat ... was bei dir ganz offensichtlich nicht der Fall ist.
 
Ich habe nicht wegen Minecraft mit Java angefangen.
ich habe nur das mit dem auslesen aus dem Internet genommen habe den rest habe ich selbst geschrieben tut mir leid das ich nicht seit jahren programmiere deswegen habe ich es ja auch unter "anfänger" gepostet ......
 
Ah ... wenn du also NICHT wegen MC mit Java angefangen hast und schon mit ArrayList rumspielst solltest du eigentlich wissen wie es richtig geht. Den Tipp habe ich dir gegeben.

(Was auch gehen würde : gleich die ganze List so wie sie ist speichern / laden / verwenden - Stichwort : Serializable)
 
Bin grade erst beim theme ArrayLists ich arbeite an einem Plugin für MC um mir das Gelernte besser einzusprägen , und danke ich werde mal gucken
 
Okay auslesen gibt keine probleme mehr aber beim speichern gibt es immer noch probleme , mit "Serializable" kann ich auch keine array liste in einem .yml File speichern so das die Verzögerung durch
Code:
		for(String savePlaceBlock : saveBlockCopy)
		{
				writeToFile += savePlaceBlock+freizeile;

		}

immer noch da ist
 
Erlich : ganz falsche Idee. Wenn du Java lernen willst dann mach das mit halbwegs "normalen" Übungen. Ein Bukkit-Plugin ist hier wohl die falsche Wahl da du dich auch mit einer weiteren API sowie deren Eigenenheiten auseinandersetzen musst deren Grundlagen du noch nicht mal gelernt hast.

Was "Serializable" ist hast du überhaupt nicht verstanden (wahrscheinlich nicht mal gegoogelt). Ansonsten würdest du nicht sagen das es mit diesem Code-Stück nicht gehen würde.

Ich wiederhole den Tipp noch mal in anderer Form : deine Performance-Bremse ist das du mit einem riesigen String arbeitest.

Mit serialization würde das so aussehen

Java:
public ArrayList<String> getFileContent() throws Exception
{
	ObjectInputStream obIn=new ObjectInputStream(new FileInputStream(myFile));
	return (ArrayList<String>)obIn.readObject();
}

Nicht mehr und nicht weniger. Speichern würde dann so aussehen

Java:
public void writeBlockSaveFile(ArrayList<String> list) throws Exception
{
	ObjectOutputStream obOut=new ObjectOutputStream(new FileOutputStream(myFile));
	obOut.writeObject(list);
}

Der Unterschied wäre das die entstehende .yml Datei (btw : YML ist hier die falsche Endung denn das YML-Format schreibt vor wie es aufgebaut ist was du komplett ignorierst. Die Bukkit-API sollte hierfür was bereitstellen.) nun ein Java-Objekt ist was man so nicht mehr direkt editieren kann.

Um das ganze also String-based umzusetzen würde ich es so machen

Java:
public ArrayList<String> getFileContent() throws Exception
{
	ArrayList<String> list=new ArrayList<String>();
	BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream(myFile)));
	String line="";
	while((line=in.readLine())!=null)
	{
		list.add(line);
	}
	return list;
}

Damit hast du dann auch direkt deine "saveBlock" List und kannst dir den zweiten Code sparen.

Speichern wiederum umgekehrt

Java:
public void writeBlockSaveFile(ArrayList<String> list) throws Exception
{
	PrintStream out=new PrintStream(new FileOutputStream(myFile));
	for(String line : list)
	{
		out.println(line);
	}
}

Das ist alles.

Diesen ganzen String-Kram kannst du komplett löschen. Damit sparst du deutlich RAM und CPU und das ganze sollte auch noch relativ schnell laufen.

Da du ja leider nicht den Code gepostet hast mit dem das Laden nun läuft kann ich natürlich nicht beurteilen was da jetzt noch für Fehler drin sind, aber mit ein bisschen Wissen und Kenntnis der API (vor allem wie man mit der Doc arbeitet) wäre das ganze deutlich einfacher und performanter gewesen.

Und gewöhn dir bitte an [noparse]
Java:
[/noparse]-Tags zu verwenden.

Sowas sollte man echt drauf haben wenn man ein Bukkit-Plugin schreiben will. Mal ganz davon abgesehen das du vermutlich nicht mal wirklich weist was Vererbung und Interfaces sind; Wissen was du dafür nämlich brauchst. Auch ist die verwendung von "public" ein Anzeichen dafür das du mit "Datenkapselung" nicht viel anfangen kannst, denn man greift nie direkt auf Variablen zu sondern immer über Getter und Setter und hält den Scope so klein wie möglich.

Ich empfehle dir wirklich erstmal die Grundlagen und notwendige erweiterte Kenntnisse zu lernen bevor du dich an ein Bukkit-Plugin machst. Außerdem solltest du dich mit der Bukkit-API befassen wofür bei Fragen die Bukkit-Foren deutlich besser sind als dieses hier.
 
Nur als verständnis Frage: Du willst etwas ähnliches machen wie LogBlock oder HawkEye? Oder meinst du mit Schützen Worldguard. Für ersteres empfielht sich nämlich eher eine MySQL Datenbank. Sowas als Flatfile zu speichern geht schwer auf die Serverleistung. Übrigens glaube ich auch, dass du auf der bukkit Seite besser aufgehoben bist.
 
Nein nicht ganz , ich schreibe an einem Plugin womit man die Exp für alles einstellen kann , nun gibt es aber immer wieder exp wenn man den block wieder plaziert dies soll nur 20-30k zeilen schnell speichern und laden können das geht nun , danke an J7Dev...
Und ich kenne mich bereits mit vererbung und interfaces aus.

Da das ja nicht so mit bukkit zu tuen hat habe ich es hier gepostet 🙂
 
Mich würde gerne mal der gesamte Code interessieren was man da noch für Anfängerfehler finden würde. Ich bin mir sicher das man da noch so einige Performance-Bremsen lösen kann.

Außerdem : wenn Mojang es so entwickelt hat das du z.B. einen IronOre-Block abbaust, dafür XP bekommst, diesen selbst neu setzt und beim erneuten Abbauen wieder XP bekommst ... dann würde ich das eher mal im Mojang-Bugtracker melden oder nach entsprechenden Plugins suchen (gibt es bestimmt) anstatt mir ohne Grundlagen und mit vielen Anfängerfehlern selbst was zusammenbasteln zu wollen. Denn dafür reichen deine Java-Grundlagenkenntnisse wie man ja gesehen hat scheinbar nicht aus und das ganze besteht großteil nur aus zusammengeklicktem ausm Netz (wie nun auch mein Code-Stück Teil deines Plugins sein dürfte).
 
Wie gesagt der code ist komplett selbst geschrieben das einzigste was ich aus dem internet kopiert habe war der teil zum schreiben und lesen von dateien
 
Kann ich erlich gesagt nich ganz glauben. Sich mit der Bukkit-API so gut auskennen um n Block-Filter zu basteln OHNE dabei vorlage von anderen Codes zu nutzen und dann nicht mal einfachste Java-File-I/O-Basics drauf haben ... sorry ... das passt einfach nich zusammen. Ich arbeite seit einige Jahren mit Java und habe schon viele "Anfänger" gesehen ... auch schon vor dem Minecraft-Hype ... aber es passt halt irgendwie nicht das man sich mit einer komplexen API auskennt und mit dieser oder Vorlagen arbeiten kann und dann nicht mal einfachste Java-Basics auf die Reihe bekommt. Aber naja ... würde mich wie gesagt nicht wundern wenn man noch etliche andere Fehler finden würde.
 
Mal ganz OT:
Man bekommt XP's nur von Erzen die keine Erzen droppen. Coal ore droppt keine Ore sondern ein Kohelstück -> XP (selbes bei Lapis). Iron Ore droppt Iron Ore daher keine XP.
 
So genau kenn ich mich mit der 1.3.x noch nicht aus ... wäre aber interessant zu wissen was mit SilkTouch passiert ...
 
Jup ich hab bestimmt mehrere Sachen drinne die den Server zwar nicht merklich ausbremsen aber trotzdem ressourcen fressend ist ,
Und sowas zu erstellen ist doch sehr simpel.

@Thoosequa
Mit meinem Plugin kannst du Exp für alle Blöcke einstellen , selbst Dirt kann dir exp geben 🙂
 
Jup ich hab bestimmt mehrere Sachen drinne die den Server zwar nicht merklich ausbremsen aber trotzdem ressourcen fressend ist ,
Und sowas zu erstellen ist doch sehr simpel.

@Thoosequa
Mit meinem Plugin kannst du Exp für alle Blöcke einstellen , selbst Dirt kann dir exp geben 🙂

Ahh ... es ist also simpel mit der Bukkit-API Plugins für eine bestimmte Aufgabe zu erstellen OHNE Java-Basics drauf zu haben ? -> "ausm-netz-zusammen-ge-klicktes-was-nich-läuft-SCHROTT".

Lern mal Java und die Basics ... dann musst du das Forum hier nich flooden.
 
Ganz ehrlich , dies ist ein forum für ANFÄNGER und das Plugin läuft nicht wie Schrott.
Nur weil ich noch nicht beim Speichern/laden von Daten das heißt nicht das ich mir alles aus dem internet zusammen klicke !
 

Zurück
Oben