PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Java] Datei parsen - Inhalt auslesen und in Array packen


Mark
2010-06-29, 03:42:51
Ich bin blutiger Javaanfaenger und wuerde mich freuen wenn mir jemand bei diesem problem helfen koennte. :)

Ich habe eine Textdatei die so aufgebaut ist:

-

#FOLDER
ID=72
NAME=Rezepte
CREATED=1277428841
UNIQUEID=46A3B4F4C08B9B418C89AE02D80F8E61

#URL
ID=73
NAME=Tiramisu Recipe - Taste.com.au
URL=http://www.taste.com.au/recipes/8677/tiramisu
CREATED=1274945262
DESCRIPTION=Tiramisu recipe
UNIQUEID=00D083E16407114EB4E66D0133DDB1EE

#URL
ID=74
NAME=Xiao Long Bao – Shanghai Steamed Soup Dumplings | Steamy Kitchen Recipes
URL=http://steamykitchen.com/88-xiao-long-bao-shanghai-steamed-soup-dumplings.html
CREATED=1275562921
UNIQUEID=0937A6C6F450524DB90A7240680CB350

-

#FOLDER
ID=75
NAME=Android News
CREATED=1277768148
UNIQUEID=203AE8E1D8C4AD4191463D863136369C

#URL
ID=76
NAME=Android Central
URL=http://www.androidcentral.com/
CREATED=1277768153
VISITED=1277768176
UNIQUEID=D796CCC1B697AA4681D6EBFD472D748E

#URL
ID=77
NAME=Android Police
URL=http://www.androidpolice.com/
CREATED=1277768257
DESCRIPTION=Android Police
UNIQUEID=04B5B33015EC964A9658ED6A6E366935

-



Vielleicht erkennt ja jemand die Herkunft dieser Datei. Es ist die Datei in welcher Opera die Bookmarks speichert.


Ich wuerde nun gerne diese Datei auslesen und ein Array aus "Folder"-Name und den einzelnen Unterpunkten bilden. Es soll aber nur ein bestimmter "Folder"-Baum ausgelesen werden.

Ib obigen Beispiel soll z.B. nur der Baum "Rezepte" ausgelesen werden. Am Ende haette ich gerne ein Array bestehend aus:

ID=73
NAME=Tiramisu Recipe - Taste.com.au
URL=http://www.taste.com.au/recipes/8677/tiramisu

ID=74
NAME=Xiao Long Bao – Shanghai Steamed Soup Dumplings | Steamy Kitchen Recipes
URL=http://steamykitchen.com/88-xiao-long-bao-shanghai-steamed-soup-dumplings.html

usw.


Dieses Array soll dann in eine seperate Textdatei eingefuegt werden, und zwar diese hier:

Opera Preferences version 2.1
; Do not edit this file while Opera is running
; This file is stored in UTF-8 encoding

[Personalbar.alignment]
Alignment=0
Auto alignment=0
Old visible alignment=2
Collapse=1

[Hotlist.alignment]
Alignment=0
Auto alignment=0
Old visible alignment=1
Collapse=0

[Document Toolbar.content]
ButtonSet, Combined Back Forward
Button1, -119414254=Wand
Address2
Button3, -512239998=Enable mediumscreen mode | Disable mediumscreen mode
Button4, 870715797=Go
Button5, -1393253531=Stop | Reload, , , -1705826954
Button6, -773844987="Show popup menu, "Browser Bookmarks Menu", , , "Bookmarks""

[Hotlist Panel Selector.content]
Bookmarks, 0
Widgets, 1


Alignment=0
Auto alignment=0
Old visible alignment=2
Collapse=1

[Site Navigation Toolbar.alignment]
Alignment=2
Auto alignment=0
Old visible alignment=2
Collapse=1

[Document View Toolbar.alignment]
Alignment=0
Auto alignment=0
Old visible alignment=2
Collapse=1

[Start Toolbar.alignment]
Alignment=0
Auto alignment=0
Old visible alignment=2
Collapse=1

[Start Toolbar.content]
Button0, 380699176=Go to homepage
Button1, 376069807="Show popup menu, "Internal Popular List", , , "Top10""
Button2, -773844987="Show popup menu, "Browser Bookmarks Menu", , , "Panel Bookmarks""
Spacer3, 1
Button4, "My Opera - Opera Skins"=Go to page, "http://my.opera.com/community/customize/skins/?show=rate", 1

[Document Toolbar.alignment]
Alignment=2
Auto alignment=0
Old visible alignment=2
Collapse=1

[Document Toolbar.style]
Button type=2
Button style=0
Large Images=0
Wrapping=0
Maximum Button Width=0
Grow To Fit=0
Mini Buttons=0
Button Skin=Addressbar Button Skin

[Pagebar.alignment]
Alignment=2
Auto alignment=0
Old visible alignment=2
Collapse=1

[Document View Toolbar.content]
[B]Button0, "Tiramisu Recipe - Taste.com.au"=Go to page, "http://www.taste.com.au/recipes/8677/tiramisu", 1
Button1, "Name2"=Go to page, "http://link.2", 1
Button2, "Name3"=Go to page, "http://link.3", 1

usw

[Menu Button Toolbar.alignment]
Alignment=2
Auto alignment=0
Old visible alignment=2
Collapse=1

[Status Toolbar.alignment]
Alignment=0
Auto alignment=0
Old visible alignment=4
Collapse=1

[Status Toolbar.style]
Button type=2
Button style=0
Large Images=0
Wrapping=0
Maximum Button Width=0
Grow To Fit=0
Mini Buttons=1
Button Skin=Statusbar Button Skin

[Pagebar Tail.alignment]
Alignment=2
Auto alignment=0
Old visible alignment=2
Collapse=1

[Personalbar.style]
Button style=3
Large Images=0
Wrapping=2
Maximum Button Width=160
Grow To Fit=0
Mini Buttons=0
Button Skin=Personalbar Button Skin

[Document View Toolbar.style]
Button type=2
Button style=3
Large Images=0
Wrapping=2
Maximum Button Width=0
Grow To Fit=0
Mini Buttons=0
Button Skin=Viewbar Button Skin

[Customize Toolbar Custom.content]
Button0, "Nick"="External action, "Go%20to%20nickname,,,,%20Bookmark%20Visited", , "Nick""
Button1, "Open"="External action, "Open%20web%20turbo%20dialog,,,%22Open%22", , "Open""
Button2, "Open1"="About Web Turbo Mode, , , "Open1", "%22Menu%22""
Button3, "Open11"="Open Web Turbo Dialog, , , "Open11", "%22Menu%22""
Button4, "Turbo"="Open Web Turbo Dialog, , , "Turbo", "%22Menu%22""
Button5, "Turbo"="Open Web Turbo Dialog, , , "Turbo", "%22Menu%22""
Button6, "Turbo1"="External action, "Enter%20access%20key%20mode,,,%22Turbo1%22,Prefs%20Network", , "Turbo1""

[Pagebar Tail.content]
Button0, -1726668283="Show popup menu, "Closed Pages Menu", , , "Trash large" + Show hidden popup menu, "Closed Pages Menu""
Spacer1, 1
CompressionRate2

[Status Toolbar Head.alignment]
Alignment=4
Auto alignment=0
Old visible alignment=4
Collapse=1

[Status Toolbar Tail.alignment]
Alignment=4
Auto alignment=0
Old visible alignment=4
Collapse=1

[Site Navigation Toolbar.content]


[Site Navigation Toolbar.style]
Button type=2
Button style=3
Large Images=0
Wrapping=2
Maximum Button Width=0
Grow To Fit=0
Mini Buttons=0

[Mail Header Toolbar.content]
Button0, , 160="Show popup menu, "Internal Access Points", , "Unread""

[Pagebar Head.alignment]
Alignment=2
Auto alignment=0
Old visible alignment=2
Collapse=1


Und zwar zwischen "[Document View Toolbar.content]" und "[Menu Button Toolbar.alignment]". Wen es interessiert, dies ist die Datei in der Opera das layout fuer die Toolbar speichert.



Wie realisiere ich das Ganze am Besten?



Das Auslesen habe ich bereits:

FileInputStream fis = new FileInputStream("bookmarks.adr");
BufferedInputStream bis = new BufferedInputStream(fis);

InputStreamReader reader = new InputStreamReader(bis);
char[] chars = new char[1024];
int length = 1;
StringBuffer text = new StringBuffer();

while (length > 0) {
length = reader.read(chars);

if (length >= 0)
text.append(chars, 0, length);
}
System.out.println(text.toString());
String inhalt = text.toString();

Und dies hier benutze ich um den "Anfangspunkt", naemlich den Eintrag des auszulesenden Folder-Baums zu finden:


String folder = "Rezepte"

if (wildCardMatch(inhalt,"#FOLDER\r\n\tID="+"*"+"\r\n\t"+"NAME="+folder+"\r\n\tCREATED")){

System.out.println("Passenden Eintrag gefunden!");
};



public static boolean wildCardMatch(String text, String pattern)
{
// Create the cards by splitting using a RegEx. If more speed
// is desired, a simpler character based splitting can be done.
String [] cards = pattern.split("\\*");

// Iterate over the cards.
for (String card : cards)
{
int idx = text.indexOf(card);

// Card not detected in the text.
if(idx == -1)
{
return false;
}

// Move ahead, towards the right of the text.
text = text.substring(idx + card.length());
}

return true;
}

}






Doch wie komme ich nun an die Unterpunkte?

gst
2010-06-29, 08:48:04
Am einfachsten machst du nen BufferedReader um den Reader und kannst komfortable per readLine() auf die einzelnen Zeilen zugreifen, danach matchen und je nach dem verarbeiten.

Der_Donnervogel
2010-06-29, 22:22:41
Das ganze Parsen geht mit deutlich weniger Aufwand würde ich sagen. Man konzentriert sich nur auf die Zeilen die interessant sind. Jedes Folder wir durch #FOLDER eingeleitet. Weiters wüsste man (auch wenns für die Aufgabe nicht relevant ist), dass jedes Folder mit einer Zeile "-" endet. Weiters fängt jedes Subelement mit "#" an. Man kann also ähnlich wie man es bei einem Sax-Parser für XML machen würde, einfach durchlaufen und die Elemente betrachten die einen interessieren. Ich gehe beim Output davon aus, dass nur ID, NAME und URL bei den Ausgaben interessant sind (wie im Beispiel angegeben). Weiters muss noch eine Leerzeile am Ende jedes Elements sein. Viel Code muss man nicht schreiben:
package test2;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;


public class Test {

public static void main(String[] args) throws Exception {
BufferedReader buf = new BufferedReader(new FileReader("Test.txt"));
String line;
String currentFolder = null;
boolean isFolder = false;
Map<String, List<String>> folders = new TreeMap<String, List<String>>();
while ((line = buf.readLine()) != null) {
line = line.trim();
if (line.startsWith("#FOLDER")) {
isFolder = true;
} else if (line.startsWith("#")) {
isFolder = false;
folders.get(currentFolder).add("");
} else {
if (line.startsWith("NAME")) {
if (isFolder) {
currentFolder = line.substring(5);
folders.put(currentFolder, new LinkedList<String>());
}
}
if (!isFolder) {
if (line.startsWith("ID") || line.startsWith("NAME") || line.startsWith("URL")) {
folders.get(currentFolder).add(line);
}
}
}
}
System.out.println("Rezepte");
for (String s : folders.get("Rezepte")) {
System.out.println(s);
}
}
}

Wobei in dem Code die Folder in einer Map gespeichert werden, die über den Namen angesprochen werden können. Falls es also mehrere Unterfolder (falls es so etwas gibt) gibt, dann werden alle Rezepte raus gesucht, egal wo sie sind. Ich denke das ist im Sinne der Aufgabe. Falls dem nicht so ist, müsste natürlich die Speicherung angepasst werden.

Edit: Übrigens, die führenden Leerzeichen jeder Zeile werden per trim() entfernt. Falls die nötig sind, müsste man entweder anders coden, oder sie am Ende wieder ergänzen. Wenn man trim() verwendet, vereinfacht sich natürlich das Parsen, da man die gesuchten Elemente mit startsWith bequem suchen kann.

Falls es noch Fragen bezüglich einiger Elemente wie z.B. Map gibt, dann bitte fragen. Ich hoffe mal der Code ist auch für einen Anfänger halbwegs verständlich.

Mark
2010-06-30, 06:37:40
Ich hatte das ganze zwischenzeitlich schon geloest, jedoch bei weitem nicht so elegant wie diese Loesung ;)

Da nur ein "Folder" ausgelesen werden soll, habe ich es so geloest:
(bin nicht an meinem Rechner, daher kein Code, nur grobe Funktionsweise)

Ich habe zuerst die ganze Textdatei in Array gepackt. Danach habe ic jede Zeile auf den Wert "#Folder" untersucht und wenn die uebernaechste Zeile das gewuenschte Wort enthaelt (in diesem Beispiel "Rezepte") eine weitere Schleife gestartet, die mir alle Unterpunkte liefert bis ein weiteres "Folder" oder ein "-" gefunden wird (oder die Datei zu Ende ist).

AlecWhite
2010-06-30, 18:08:01
ganz ehrlich: Für sowas wurden Regex gemacht. Datei einlesen, entsprechenden Regex drüberlaufen lassen, ergebnisse speichern. Fertig.