Discussion:
Problem mit DatenStrukturierung
(zu alt für eine Antwort)
Ulf Kadner
2004-06-17 13:15:27 UTC
Permalink
Hallo est mal!

Ich bin noch relativ unerfahren mit JAVA (hab gestern das erste mal java
probiert) und stehe vor meinem ersten Problem.

Ich moechte aus einer *.ini-Datei deren Daten auslesen um diese an anderer
Stelle weiter verarbeiten zu koennen.

In PHP wuerde ich dafuer einfache ein Array erstellen und gut ist, aber in
JAVA steh ich auf dem Schlauch.

Mal angenommen die *.ini sieht so aus:

foo = 1

[AbschnittA]
foo1 = bar1
foo2 = bar2

[AbschnittB]
foo1 = bar1
foo2 = bar2

Irgendwie komme ich nicht weiter, da ich nicht weiss, welches Format ich
nutzen soll, um den Inhalt der ini korrekt abzuspeichern (so das ich jedes
Element erreichen kann) um diese von der Methode zurueck geben zu lassen.

Das zeilenweise auslesen und auseinandernehmen der Daten klappt bereits.

Meine Ueberlegung ging Richtung Hashtable() aber scheinbar ist es nicht
moeglich einem Hash-Key als Wert eine komplette Hashtable zuzuweisen.

Ich waere Euch dankbar, wenn Ihr mir mal den richtigen Weg aufzeigen
koenntet bzw. nen paar nuetzliche Tips gebt.

MfG, Ulf
Stefan Ram
2004-06-17 13:31:17 UTC
Permalink
Post by Ulf Kadner
foo = 1
[AbschnittA]
foo1 = bar1
foo2 = bar2
[AbschnittB]
foo1 = bar1
foo2 = bar2
Die .ini-Dateien sind doch recht eingeschränkt. Unotal ist da
nicht viel komplizierter und erlaubt unbeschränkte
Verschachtelungen, wobei es noch einfacher und orthogonaler
als XML ist. Sei die Datei "example3.uno" beispielsweise:

< foo = 1
[AbschnittA] =
< foo1 = bar1
foo2 = bar2 >
[AbschnittB] =
< foo1 = bar1
foo2 = bar2 >>

Das folgende Programm zeigt das daraus erstellte Objekt,
welches im wesentlichen eine verschachtelte Struktur aus
java.util.Map- und java.util.List-Objekten ist.

public class Example3
{ public static final void main( final String[] args )
throws Exception
{ final Unoscan scanner = new Unoscan( "f", "example3.uno");
final Unobuild builder = new Unobuild( scanner );
System.out.println( builder.expression( scanner.getnext())); }}

Ausgabe (manuell auf drei Zeilen aufgeteilt):

{foo=1, sbody=[],
AbschnittB={sbody=[], foo2=bar2, foo1=bar1},
AbschnittA={sbody=[], foo2=bar2, foo1=bar1}}

Die beiden experimentellen Klassen "Unoscan" und "Unobuild"
sind auf der Unotal-Seite im Web zu finden.
Ulf Kadner
2004-06-17 14:22:08 UTC
Permalink
Post by Stefan Ram
Die .ini-Dateien sind doch recht eingeschränkt.
Leider :-(
Post by Stefan Ram
Unotal ist da nicht viel komplizierter und erlaubt unbeschränkte
Verschachtelungen, wobei es noch einfacher und orthogonaler als XML
ist.
Das Problem ist nur, dass ich keinerlei Einfluss darauf habe! Die
Ini-Datei(en) ist/sind Bestandteil eines anderen Programmes, von welchem
ich keinen Sourcecode besitze und bei dem ich auch kein Recht hab dies zu
veraendern. Daher bleibt mir keine andere Wahl als mich mit den
Gegebenheiten anzufreunden und mein Tool anhand dieser zu erstellen.
Post by Stefan Ram
< foo = 1
[AbschnittA] =
< foo1 = bar1
foo2 = bar2 >
[AbschnittB] =
< foo1 = bar1
foo2 = bar2 >>
Das folgende Programm zeigt das daraus erstellte Objekt, ...
public class Example3
{ public static final void main( final String[] args )
throws Exception
{ final Unoscan scanner = new Unoscan( "f", "example3.uno");
final Unobuild builder = new Unobuild( scanner );
System.out.println( builder.expression( scanner.getnext())); }}
Danke fuer das Beispiel! *.uno ist auf jeden Fall leistungsfaehiger, aber
da ich beim schreiben eines Programmes die Wahl habe in welchen Format ich
Konfigurationsdaten speichern will, wuerde ich mich wahrscheinlich eher
fuer das xml-Format entscheiden, da dieses ja mittlerweile doch schon
recht bekannt ist und ausserdem wohl auch die groesste Flexibilitaet
besitzt. Obwohl man sich da nicht so festlegen sollte! :x Meist kommts eh
anders als man denkt. :)

Auf jeden Fall hab ich Deinen Code mal in mein (noch sehr kleines)
Code-Archiv aufgenommen. Danke nochmal!

MfG, Ulf
Post by Stefan Ram
Die beiden experimentellen Klassen "Unoscan" und "Unobuild" sind auf
der Unotal-Seite im Web zu finden.
Albert Uerz
2004-06-17 13:32:21 UTC
Permalink
Hi Ulf,


http://www.uni-koeln.de/rrzk/kurse/unterlagen/java/oop/samples/


die Datei properties.zip löst Deine Probleme

Albert
Stefan Ram
2004-06-17 13:49:12 UTC
Permalink
Post by Albert Uerz
http://www.uni-koeln.de/rrzk/kurse/unterlagen/java/oop/samples/
die Datei properties.zip löst Deine Probleme
Zum einen stimmt die Datei-URI dort nicht, aber ein richtiger
Java-Programmierer kann schon rausfinden, wie die richtig URI
lauten muß.

Aber Abschnitte in der Datei (darum ging es dem OP), sind dann
damit immer noch nicht mögich.
Albert Uerz
2004-06-17 13:57:29 UTC
Permalink
Hi Stefan,
Post by Stefan Ram
Zum einen stimmt die Datei-URI dort nicht, aber ein richtiger
Java-Programmierer kann schon rausfinden, wie die richtig URI
lauten muß.
stimmt ;-) , hier ist der Code:

// Properties:

// Auflisten aller Systemproperties,
// Abfragen einer bestimmten Systemproperty,
// Lesen und Schreiben von Propertydateien.

import java.io.*;
import java.util.Properties;

public class ConsApp {

static BufferedReader in;
static PrintWriter out;

public static void main(String args[]) throws IOException {
out = new PrintWriter(new OutputStreamWriter(System.out,
"Cp437"), true);
in = new BufferedReader( new InputStreamReader(System.in,
"Cp437"));

try {
out.println("Properties");
out.println("----------");

// Wir schreiben zuerst mal alle Systemproperties und ihre
// Werte in einen
// StringWriter, damit wir die längliche Auflistung
// seitenweise anzeigen können.
// Für das ganze könnte man einen Anzeigefilter schreiben.

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter( sw );
System.getProperties().list(pw);
String propertyListing = sw.toString();

BufferedReader sr = new BufferedReader( new
StringReader(propertyListing) );
String line; int lineCount = 0;
while ( (line = sr.readLine()) != null ) {
out.println(line);
lineCount++;
if (lineCount == 15) {
lineCount = 0;
out.println("Bitte Enter eingeben, um
weiterzumachen.");
in.readLine();
}
}

out.println();
out.println("Es folgt die Ausgabe der Property
java.version:");
out.println(System.getProperty("java.version"));

Properties myproperties = new Properties();
myproperties.put("program.version", "1.0");
myproperties.put("program.author", "M. Holst");

BufferedOutputStream os = new BufferedOutputStream(new
FileOutputStream("myprops.txt"));
myproperties.save(os, "Program Properties");
os.close(); // wichtig, um den gepufferten Inhalt wirklich
// hinauszuschreiben!

myproperties = new Properties(); // neu anfangen, um das
//Einlesen zu demonstrieren.
myproperties.load(new BufferedInputStream( new
FileInputStream("myprops.txt")));
out.println("Es folgen die selbstdefinierten Properties.");
myproperties.list(out);

} catch (Throwable e) { // Error oder Exception
out.println("Programmabbruch wegen Laufzeitfehlers:");
e.printStackTrace(out);
}
finally {
out.println();
out.println("To exit, press Enter one or more times, or
Ctrl-C.");
in = new BufferedReader( new InputStreamReader(System.in,
"Cp437") );
// Neuer Reader, weil der alte auf EOF stehen kann.
// In diesem Zustand hält er per readLine() das Programm
// nicht an.
in.readLine(); // Wenn ein einziges readLine(); hier nicht
//ausreicht, um das Programm anzuhalten,
// setze man einfach mehrere ein.
}
}
}
Post by Stefan Ram
Aber Abschnitte in der Datei (darum ging es dem OP), sind dann
damit immer noch nicht mögich.
Eigentlich schon.

Bis denne
Albert
Albert Uerz
2004-06-17 14:05:33 UTC
Permalink
Uuups,
Post by Stefan Ram
Aber Abschnitte in der Datei (darum ging es dem OP), sind dann
damit immer noch nicht mögich.
falsch gelesen, sorry

Albert
Albert Uerz
2004-06-17 14:07:07 UTC
Permalink
Hi Stefan,
Post by Stefan Ram
Zum einen stimmt die Datei-URI dort nicht, aber ein richtiger
Java-Programmierer kann schon rausfinden, wie die richtig URI
lauten muß.
stimmt , hier ist der Code:

// Properties:

// Auflisten aller Systemproperties,
// Abfragen einer bestimmten Systemproperty,
// Lesen und Schreiben von Propertydateien.

import java.io.*;
import java.util.Properties;

public class ConsApp {

static BufferedReader in;
static PrintWriter out;

public static void main(String args[]) throws IOException {
out = new PrintWriter(new OutputStreamWriter(System.out,
"Cp437"), true);
in = new BufferedReader( new InputStreamReader(System.in,
"Cp437"));

try {
out.println("Properties");
out.println("----------");

// Wir schreiben zuerst mal alle Systemproperties und ihre

// Werte in einen
// StringWriter, damit wir die längliche Auflistung
// seitenweise anzeigen können.
// Für das ganze könnte man einen Anzeigefilter schreiben.

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter( sw );
System.getProperties().list(pw);
String propertyListing = sw.toString();

BufferedReader sr = new BufferedReader( new
StringReader(propertyListing) );
String line; int lineCount = 0;
while ( (line = sr.readLine()) != null ) {
out.println(line);
lineCount++;
if (lineCount == 15) {
lineCount = 0;
out.println("Bitte Enter eingeben, um
weiterzumachen.");
in.readLine();
}
}

out.println();
out.println("Es folgt die Ausgabe der Property
java.version:");
out.println(System.getProperty("java.version"));

Properties myproperties = new Properties();
myproperties.put("program.version", "1.0");
myproperties.put("program.author", "M. Holst");

BufferedOutputStream os = new BufferedOutputStream(new
FileOutputStream("myprops.txt"));
myproperties.save(os, "Program Properties");
os.close(); // wichtig, um den gepufferten Inhalt wirklich
// hinauszuschreiben!

myproperties = new Properties(); // neu anfangen, um das
//Einlesen zu demonstrieren.
myproperties.load(new BufferedInputStream( new
FileInputStream("myprops.txt")));
out.println("Es folgen die selbstdefinierten Properties.");
myproperties.list(out);

} catch (Throwable e) { // Error oder Exception
out.println("Programmabbruch wegen Laufzeitfehlers:");
e.printStackTrace(out);
}
finally {
out.println();
out.println("To exit, press Enter one or more times, or
Ctrl-C.");
in = new BufferedReader( new InputStreamReader(System.in,
"Cp437") );
// Neuer Reader, weil der alte auf EOF stehen kann.
// In diesem Zustand hält er per readLine() das Programm
// nicht an.
in.readLine(); // Wenn ein einziges readLine(); hier nicht
//ausreicht, um das Programm anzuhalten,
// setze man einfach mehrere ein.
}
}
}
Post by Stefan Ram
Aber Abschnitte in der Datei (darum ging es dem OP), sind dann
damit immer noch nicht mögich.
uups, da habe ich wohl etwas falsch verstanden, sorry

Bis denne
Albert
Ulf Kadner
2004-06-17 14:52:46 UTC
Permalink
Post by Albert Uerz
http://www.uni-koeln.de/rrzk/kurse/unterlagen/java/oop/samples/
die Datei properties.zip löst Deine Probleme
Leider kann ich nicht ganz nachvollziehen, wie mich das im zip enthaltene
ConsApp.java bei meinem Vorhaben unterstuetzen soll! Ist zwar alles gut
dokumentiert, aber effektiv scheint diese Klasse etwas anderes zu machen,
als das von mir gewuenschte! Wenn ich falsch liege, bitte korrigiere mich!

Du nutzt "java.util.Properties", welches aber laut Handbuch "ein auf
String-Paare spezialisiertes Dictionary" repaesentiert.

Ich glaub damit kann ich meine Problemstellung nicht loesen (oder etwa
doch?)!

Das was ich da speichern/weitergeben moechte ist passt da nicht rein.

[Datenset1]
foo1 = bar1
foo2 = bar2

[Datenset2]
foo1 = bar3
foo2 = bar4

wird zu:

Datenset1 enthaelt mehrere Datensets vom Type Hashtable Datenset2 enthaelt
mehrere Datensets vom Type Hashtable usw. usf.

Es muessen also alle Schluessel-Wert-Beziehungen erhalten bleiben.

und auf jedes der einzelnen Elemente, sowie Subelemente moechte ich
gezielt zugreifen koennen. Nur mal als Beispiel wies in PHP aussehen
wuerde ... (ist momentan leider noch die einzige P-Sprache die ich richtig
beherrsche)

$data = array( 'Datenset1' => array( 'foo1'=>'bar1', 'foo2'=>'bar2' ),
'Datenset2' => array( 'foo1'=>'bar3', 'foo2'=>'bar4' )
);

MfG, Ulf
Peter Büttner
2004-06-17 18:40:14 UTC
Permalink
Ulf Kadner wrote:

[...]
Post by Ulf Kadner
Du nutzt "java.util.Properties", welches aber laut Handbuch "ein auf
String-Paare spezialisiertes Dictionary" repaesentiert.
Ich glaub damit kann ich meine Problemstellung nicht loesen (oder etwa
doch?)!
Das was ich da speichern/weitergeben moechte ist passt da nicht rein.
[Datenset1]
foo1 = bar1
foo2 = bar2
[Datenset2]
foo1 = bar3
foo2 = bar4
Datenset1 enthaelt mehrere Datensets vom Type Hashtable Datenset2 enthaelt
mehrere Datensets vom Type Hashtable usw. usf.
Es muessen also alle Schluessel-Wert-Beziehungen erhalten bleiben.
und auf jedes der einzelnen Elemente, sowie Subelemente moechte ich
gezielt zugreifen koennen. Nur mal als Beispiel wies in PHP aussehen
Brauchst du denn unbedingt die .ini Form? (z.B. windows programme
kompatibilität)


Ansonsten kannst du auch Proerties nehmen
'In Java mach es wie die Javanesen'

Datenset1.foo1=bar1
Datenset1.foo2=bar2
Datenset2.foo1=bar3
Datenset2.foo2=bar4

Hst direkt eine Hierarchische struktur, nur halt keine Punkte in die
namen legen. Oder diese irgendwie escapen durch ein Zeichen das nie
vorkommt '§' oder irgendein unicode Ding.

mit Properties#load() laden
Properties#get( dataset + "." + key) auslesen



Grüße
Peter
--
Shell&Jar : Individual icons for jars
jMineSweeper : extended
www.PeterBuettner.de
Ulf Kadner
2004-06-17 20:14:09 UTC
Permalink
Post by Peter Büttner
Brauchst du denn unbedingt die .ini Form?
Ist vorgegeben ja! Ich habs, nach dem ich erfahren habe, das man auch
Hashtables als Werte anderer Hashtables ablegen kann nun auch so geloest.
Das ganze werd ich nur noch etwas optimieren und in die passende Klasse
packen + Errorhandling. Funktionieren tuts :)

<*******Begin*of*Code*******************************>

import java.util.*;

public class testB
{
public static void main( String[] args )
{
Hashtable hA = new Hashtable();
hA.put( "foo1", "bar1" );
hA.put( "foo2", "bar2" );
Hashtable hB = new Hashtable();
hB.put( "foo1", "bar3" );
hB.put( "foo2", "bar4" );
Hashtable hX = new Hashtable();
hX.put( "Abschnitt1", (Hashtable)hA );
hX.put( "Abschnitt2", (Hashtable)hB );
Enumeration e = hX.keys();
while( e.hasMoreElements() )
{
String Schluessel = (String)e.nextElement();
System.out.println( "[" + Schluessel + "]" );
Hashtable hCurr = (Hashtable)hX.get( Schluessel );

Enumeration ee = hCurr.keys();
while( ee.hasMoreElements() )
{
String SubSchluessel = (String)ee.nextElement();
System.out.println( " '" + SubSchluessel + "' => '" +
hCurr.get( SubSchluessel ) + "'"
);
}
}
}
}

</********END*OF*CODE******************************>

Danke noch mal an alle die mir so nett geholfen haben!

MfG, Ulf
Michael Holtermann
2004-06-17 13:57:34 UTC
Permalink
Moin Ulf!
Post by Ulf Kadner
Meine Ueberlegung ging Richtung Hashtable() aber scheinbar ist es nicht
moeglich einem Hash-Key als Wert eine komplette Hashtable zuzuweisen.
Du kannst in einer Hashtable als Werte Objects ablegen, also alles was ein
Objekt ist.
Keys wären in deinem Beispiel AbschnittA und AbschnittB, als value wäre z.B.
wieder eine Hashtable denkbar, wo dann foo1=bar1 usw. steht.

Grüße, Micha.
--
Lieber einen kleinen Beutel Kohle, als einen großen Sack mit Briketts.
Achim Peters
2004-06-17 14:09:15 UTC
Permalink
Post by Ulf Kadner
Ich moechte aus einer *.ini-Datei deren Daten auslesen um diese an anderer
Stelle weiter verarbeiten zu koennen.
Ist das Format der ini-Datei festgelegt? Sonst könntest Du Dir das Leben
mit java.util .Properties das Leben einfacher machen. Es kennt
allerdings keine Abschnitte:

foo = 1

foo1_A = bar1
foo2_A = bar2

foo1_B = bar1
foo2_B = bar2
Post by Ulf Kadner
Meine Ueberlegung ging Richtung Hashtable() aber scheinbar ist es nicht
moeglich einem Hash-Key als Wert eine komplette Hashtable zuzuweisen.
Doch, das geht. Allerdings würde ich die Hashtable eher als Value als
als Key erwarten. BTW: Der moderne Java-Programmierer nimmt i. allg.
HashMap und nicht mehr Hashtable.

Bye
Achim
Ulf Kadner
2004-06-17 15:01:32 UTC
Permalink
Post by Achim Peters
Ist das Format der ini-Datei festgelegt?
Ja leider :(
Post by Achim Peters
Post by Ulf Kadner
Meine Ueberlegung ging Richtung Hashtable() aber scheinbar ist es nicht
moeglich einem Hash-Key als Wert eine komplette Hashtable zuzuweisen.
Doch, das geht. Allerdings würde ich die Hashtable eher als Value als
als Key erwarten.
hehe :) meinte ich auch. Hab mich nur etwas ungluecklich ausgedrueckt!
Post by Achim Peters
BTW: Der moderne Java-Programmierer nimmt i. allg.
HashMap und nicht mehr Hashtable.
Haette ich wohl auch gemacht, aber das Buch was mir gestern jemand
schenkte :)) GoTo Java2 (1999) hat 900 Seiten. Logisch das ich da noch
nicht alles entdeckt habe :x, aber ich schaus mir an.

Danke, Ulf
Markus Erlmann
2004-06-18 13:52:34 UTC
Permalink
Post by Achim Peters
BTW: Der moderne Java-Programmierer nimmt i. allg.
HashMap und nicht mehr Hashtable.
Wieso eigentlich?
Post by Achim Peters
Bye
Achim
Tschüß,

Markus
Peter Büttner
2004-06-18 18:23:18 UTC
Permalink
Post by Markus Erlmann
Post by Achim Peters
BTW: Der moderne Java-Programmierer nimmt i. allg.
HashMap und nicht mehr Hashtable.
Wieso eigentlich?
Hmm,
weil Hashtable, wie Vector, aus der 1.0 Zeit kommen, von damals.
Inzwischen git es eine Collections Library deren Elemente besser
zueinander passen: List, Map, Set, Collection, Iterator...
[Frage: warum wurde das nicht in ein eigenes Package gelegt?]

Die älteren APIs wurden soweit aufgeblasen bis sie mit den neuen
kompatibel waren.
Zudem sind die älteren noch synchronized, die neueren nicht.
Synchronized braucht man beim multithreaded Zugriff, wobei
aber die Art wie die alten synchronized sind meist nicht
ausreicht, man muss es auf höherer Ebene sowieso nochmal machen.

Dazu kann man mit den neuen APIs z.B. sowas machen.

tueWas (Map map){
for(...)
}

also nur das Interface angeben, welche Map dann dahinter ist kann
man bei Bedarf austauschen.

Steht das eigentlich in der FAQ? Habe die wohl noch nie genau gelesen.

Das Swing und viele andere APIs immer noch Vector und Hashtable
versteh' ich auch nicht (ausser: never change a running system) und
man sollte es sich nicht zum Vorbild nehmen.


Bei Hashtable muss man die Daten immer 'nochmal' speichern, beim Map
interface könnte es reichen wenn man sie in seiner eigenen
Datenstruktur behält.

Banales sinnloses(?) Beispiel:
Man hat ein Object[] data. Die keys wären die indexe.
Dann könnte man eine Map rausgeben (hier reduziert und unsicher)
class MyClass{
Object[] data;
Map getMap(){
return new Map(){ // innere Klasse, hier abstrakt
Object get(Object key){
return data[((Integer)key).intValue()];
}
Object put(Object key, Object val){
int i = ((Integer)key).intValue();
Object old= data[i];
data[i]=val;
return old;
}
...


Grüße
Peter
--
Shell&Jar : Individual icons for jars
jMineSweeper : extended
www.PeterBuettner.de
Stefan Ram
2004-06-18 19:03:48 UTC
Permalink
Post by Peter Büttner
weil Hashtable, wie Vector, aus der 1.0 Zeit kommen, von damals.
Inzwischen git es eine Collections Library deren Elemente besser
zueinander passen: List, Map, Set, Collection, Iterator...
[Frage: warum wurde das nicht in ein eigenes Package gelegt?]
Zumal der Name "util" ("java.util") ziemlich nichtssagend ist.
"util" kann alles sein. Der Paketname sollte möglichst genau
sagen, was das Paket enthält, und das Paket sollte so
konstruiert sein, daß solch ein Name möglich wird (hohe
Kohäsion). Für bestimmte Klassen könnte man sich
beispielsweise "java.container" vorstellen.
Markus Erlmann
2004-06-20 13:20:45 UTC
Permalink
[ erschöpfende Erklärung ]
Gr e
Peter
Danke!
Markus

Lesen Sie weiter auf narkive:
Loading...