Stringprogramm

RelaX

Aktives Mitglied
Hallo Leute,

bin dann auch mal hier... und ich scheitere schon wieder an einer Aufgabe.. Wir sollen ein Programm schreiben das x-beliebige Dateien auf ein String durchsucht und diese dann durch einen anderen Strind ersetzt.

Ich hab das auch soweit gut hinbekommen. Mein Programm kann jetzt folgendes.
Es fragt nach einer Datei... dann nach einer zweiten Datei naja ok nicht ganz Sinn der Aufgabe aber immerhin schon etwas. Somit funktioniert, wenn man zweimal den selben Dateipfad angibt, schonmal die Ersetzung. Es fragt einen String nachdem gesucht werden soll und nach einem String das den ursprünglichen String ersetzt. Funktioniert wunderbar!!!

Jetzt mein Problem:

ich schaffe es einfach nicht raus zu bekommen wie ich beliebig viele Dateien aussuchen kann. Ich denke mal das eine ArrayList das richtige wäre und hab mich wirklich mehr als durch gelesen aber ich kann es einfach nicht umsetzen..

Das einzigste was ich noch geschafft habe ist eine ArrayList zu erstellen die die Zeilen jeweils als Array beinhaltet. Aber ich glaube das war wohl Zeitverschwendung. Würde ja dann auf mehrere Arraylisten hinauslaufen bzw x-beliebig viele. Matrix?

ich bitte wirklich dringends um hilfe ich kann echt nciht mehr...

Hier mein Programm:

Code:
import de.htw.saarland.stl.Stdin;
import java.io.*;

public class ReadDokument {

    public static void main(String[] args) throws IOException
    {
        String objekt;
        String suchstring;
        String ersetzungsstring;
        String ausgabeobjekt;

        objekt = Stdin.readlnString("Woraus soll gelesen werden?: ");
        ausgabeobjekt = Stdin.readlnString("Wohin soll geschreiben werden?: ");
        suchstring = Stdin.readlnString("Bitte Suchstring angeben: ");
        ersetzungsstring = Stdin.readlnString("Bitte Ersetzungsstring angeben: ");

        FileReader fileReader = new FileReader(new File(objekt));
        BufferedReader in = new BufferedReader(fileReader);

        
        String s = in.readLine();

        File out = new File(ausgabeobjekt);

        try {
            FileWriter ausgabe = new FileWriter(out);
            BufferedWriter raus = new BufferedWriter(ausgabe);

            while ( s != null) {
                raus.write(s.replace(suchstring, ersetzungsstring) + "\n");
                System.out.println(s.replace(suchstring, ersetzungsstring));
                s = in.readLine();
            }

            //Schließe den InputStream

            raus.close();
            ausgabe.close();

        }
        catch (IOException e) {
            System.err.println(e.toString());

        }
        in.close();
        fileReader.close();

    }
}
 

KrokoDiehl

Top Contributor
Nun, wenn du mehrere Dateien durchsuchen willst, ist die erste Frage, woher du die Information bekommst, welche Dateien. Hier gibts z.B. drei Möglichkeiten:
- Angabe eines Verzeichnisses und alle Dateien darin
- Alle Dateien mit einer bestimmten Dateiendung (auch hier wird ein Verzeichnis nötig sein)
- Der Benutzer muss die Dateien angeben

In ersterem Fall kannst du auch mit File arbeiten:
Java:
File verzeichnis = new File("C:/Programme");
File[] dateien = verzeichnis.listFiles();
for (File datei : dateien)
{
    if (datei.isFile())
    {
        // mach was
    }
    else
    {
        // hier ggfs rekursiv die Unterverzeichnisse durchsuchen
    }
}

Dies mal als Anregung, wie man alle Dateien aus einem Verzeichnis bekommt ...bzw. einer von sicher mehreren möglichen Wegen :)
 

RelaX

Aktives Mitglied
wow das ging ja mal schnell-.. echt cool.

Naja ich weiß nicht genau wie der das meinte aber ich kann mir nur vorstellen das man die dateien alle einzeln anwählen muss. Ich hab mich für die verzeichnisart entschieden..

Code:
FileReader fileReader = new FileReader(new File(objekt));

das objekt also z.b. C:\user\offentlich\testdatei.txt kann ja beliebig gewählt werden. man ist so also nicht gebunden. Klar relativ unpraktisch wenn sich alle dateien in einem Ordner befinden aber ich denke das ich das andere ja noch machen kann wenn ich das erstmal soweit hinbekommen habe mit den x-beliebigen dateien hinzufügen.

Keine idee wie ich das so realisieren kann? Ich bin wirklich am verzweifeln.
 

Purgator

Aktives Mitglied
Aloha,

ich weiß jetzt nicht was du genau realisieren willst - die Möglichkeiten hatKrokoDiehl ja schon aufgezählt.
Interessant ist für dich (neben der eigentlichen Api) vllt. folgende Seite:
How to Use File Choosers (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Swing Components)
Ich weiß ja nicht ob du schon mit FileChoosern arbeitest, oder ob der Benutzer den Pfad immer per Hand eingeben muss.
Aber um auf die Möglichkeiten zurück zu kommen:
- Angabe eines Verzeichnisses und alle Dateien darin
Wenn du das machen willst schaue dir die Methode
void setFileSelectionMode(int)
an. Dann bekommst du das Verzeichnis. Du kannst auch einfach testen ob eine Datei ein Ordner ist mit "isDirectory". Aus einem Ordner bekommst du die Dateien die enthalten sind mit "listFiles()".
- Alle Dateien mit einer bestimmten Dateiendung (auch hier wird ein Verzeichnis nötig sein)
Hierzu solltest du dir FileFilter anschauen.
- Der Benutzer muss die Dateien angeben
Wenn du FileChooser nimmst gibt es die Methode "File[] getSelectedFiles()".
Wenn du natürlich willst, dass er mehrere Dateien aus verschiedenen Ordnern angeben kann musst du das ein wenig umständlicher machen.
Du könntest ihn zum Beispiel immer Dateien aussuchen lassen und die einem mehrzeiligen Textfeld hinzufügen, bis er genug hat (also die Pfade, damit der Nutzer die sieht). Du könntest aber auch immer ein Textfeld und ein Button kombinieren. Der Button öffnet einen FileChooser und der Pfad der ausgewählten Datei kommt in das Textfeld. Das Textfeld könnte einen DocumentListener haben und sobald es Text enthält erscheint unter ihm ein neues Textfeld mit Button für eine potentielle nächste Datei.
Das ganze könntest du - um es einfach zu halten - mit einem Vertikalem BoxLayout realisieren. Die ganzen Textfelder und Buttons könntest du z.B. in einer ArrayList verwalten.

Das sind jetzt nur Lösungsmöglichkeiten die ich mir basierend auf KrokoDiehls Möglichkeiten vorstelle. Aber ich weiß wie gesagt nciht wirklich was genau du davon realisieren willst und wo genau dein Problem ist.
 

RelaX

Aktives Mitglied
nochmal dank für die schnelle antwort.

Ja woher ich die informationen herbekomme ist ja kein problem.. ich hab das so gemacht:

Code:
String objekt;
          FileReader fileReader = new FileReader(new File(objekt));
String ausgabeobjekt;
          File out = new File(ausgabeobjekt);

das funktioniert ja soweit ganz gut. Hab ja initialisiert und dann zugeordnet. Ist jetzt nicht die orginale Reihenfolge aber so in etwa.

Das Problem ist das ich jetzt nur eine Datei auswählen kann. Ich muss aber x-beliebige auswählen können und wenn ich mit der Auswahl fertig bin erfrage ich einen suchstring und ersetzungsstring. und wende das dann drauf an.

so in etwa:

So habe ich Arraylist1 ---> array[zeile1]
array[zeile2]
usw....

dann möchte ich noch eine arraylist erstellen mit genau dem selben Schema.

Arraylist2 ---> array[zeile1]
array[zeile2]
usw

wenn man jetzte möchte dann noch eine 3te oder 4te oder x beliebig viele eben.

die arraylisten heißen genau so wie der dateipfad den ich auswähle wie ichs oben gemacht habe.(objekt und ausgabeobjekt) wobei Arraylist1 = objekt(also das erste das ich wähle) und Arraylist2 = objekt(also das zweite das ich wähle) usw. beschreiben kann. Die Objekte unterscheiden sich. Ich hab nur das Problem das sich ja dann das Objekt bei der erneuten Anfrage überschreiben würde. Könnt ich das nicht wieder mit einer Arraylist lösen?

Hoffe ihr versteht das einiger Maßen.

Falls nicht dann poste ich jetzt einfach mal die Aufgabenstellung:

Code:
Aufgabe
-------
Erstellen Sie ein Java-Programm zum Suchen und Ersetzen von Texten in Dateien.
Der Aufruf soll wie folgt erfolgen:

    java Replace suchstring ersetzungsstring datei1 datei2 ....


Zu beachten:    

  - Suchstring und Ersetzungsstring müssen nichtleer und verschieden sein.
  - Es muss mindestens eine Datei angegeben sein.
  - Die Dateien müssen existierende normale Dateien sein.
  - Es muss Schreibrecht auf die Dateien bestehen.
  - Jede Datei ist zeilenweise zu durchlaufen.  Dabei ist jeweils das Suchstring
    so oft es vorkommt zu ersetzen. 
  - Überlegen Sie sich, wie Sie es hinbekommen, dass die Datei selbst wieder
    überschrieben wird.
  - Mögliche Ausnahmen sind explizit zu behandeln.


ACHTUNG:  Testen Sie Ihr Programm nur mit unwichtigen Dateien!
~~~~~~~~


ZUSATZ:   Es sind eigene Ausnahmeklassen zu verwenden!
~~~~~

Ich will mir das ja erarbeiten aber ich komm nicht mehr weiter..

Danke an alle die sich soviel Mühe mit mir geben.
 

Purgator

Aktives Mitglied
Ich hoffe das ich dich richtig verstehe ;).

Also du hast für jede Datei eine ArrayList, jedes Objekt in der ArrayList stellt eine Zeile in der Datei da.
Das die ArrayListen so heißen wie der Dateipfad verstehe ich wiederrum nicht, hoffe aber das ist nicht so schlimm...

Wenn ich es richtig verstanden habe ist dein Problem, dass eine zweite Datei die erste ArrayList überschreiben würde. Und du hast ja schon den Ansatz es mit einer weiteren ArrayList zu lösen.
Ich hoffe ich verstehe dich richtig das die verschachtelung von ArrayListen die Lösung sein soll.
Das würde in etwa so funktionieren:
Java:
ArrayList<String> datei = new ArrayList<String(); //das wäre wahrscheinlich deine derzeitige ArrayList
ArrayList<ArrayList<String>> dateien = new ArrayList<ArrayList<String>>(); //nun hättest du eine ArrayList welche ArrayListen als Objekte hat
Aber wie gesagt irgendwie habe ich gerade Verständnisprobleme, daher weiß ich nciht ob dir das nun wirklich weiter hilft.
 

tagedieb

Top Contributor
Java:
Der Aufruf soll wie folgt erfolgen:

java Replace suchstring ersetzungsstring datei1 datei2 ....

Hier steht doch schon deine Loesung :)
Du brauchst die Dateien nicht beim Benutzer zu erfragen. Sie werden dir schon via main Methode uebergeben.

Java:
	public static void main(String[] args) throws IOException {
		String suchstring = args[0];
		String ersetzungsstring = args[1];

                for (int i = 2; i < args.length; i++) {
                      String objekt = args[i];
                      // file einlesen
                      // text suchen und ersetzen und in temp file speichern
                      // original mit temp file ersetzen
                }
        }
 

RelaX

Aktives Mitglied
Ok jetzt bin ich wirklich am Ende.. kannste mir das mal genauer erklären? Ich verstehe grad nicht worauf du hinaus willst...

Code:
public static void main(String[] args) throws IOException {
        String suchstring = args[0];
        String ersetzungsstring = args[1];
 
                for (int i = 2; i < args.length; i++) {
                      String objekt = args[i];
                      // file einlesen
                      // text suchen und ersetzen und in temp file speichern
                      // original mit temp file ersetzen
                }
        }
 

tagedieb

Top Contributor
In der Aufgabenstellung ist genau beschrieben wie dein Program aufgerufen wird.

Der Aufruf soll wie folgt erfolgen:

java Replace suchstring ersetzungsstring datei1 datei2 ....


Daraus laesst sich folgendes Ableiten:
1. Deine Klasse muss 'Replace' heissen
2. Die Klasse hat keine Package. Sie liegt also im Defaulpackage
3. Uebergabeparameter
parameter 1 (index 0) = suchstring
parameter 2 (index 1) = ersetzungsstring
parameter 3 (index 2) = datei1
parameter 4 (index 3) = datei2
parameter n (index n-1) = datei n-2


Du brauchst also gar keinen Informationen vom Benutzer zu erfragen, da dir diese Angaben schon beim Programstart uebergeben werden.
 

RelaX

Aktives Mitglied
em wie soll das denn bitte gehen? Sorry wenn ich mich jetzt dumm dran stelle aber ich bin ein absoluter Anfänger was programmieren angeht. In welchem ding? ja woher soll das Programm denn wissen welche Dateien ich durchsuchen möchte und vorallem auf was das Programm suchen soll???
 

Purgator

Aktives Mitglied
Java:
public static void main(String[] args) {
...
}
Die main-Methode ist ja der Einstiegspunkt in ein Java-Programm.
Ein Java Programm wird aufgerufen, indem man in der Console
java Dateiname Parameter1 Parameter2 .... Parameterx
angibt.
Die Parameter die übergeben wurden sind dann in "args" enthalten.
Wenn nun der Aufruf
java Replace suchstring ersetzungsstring datei1 datei2 ....
vorgegeben ist, dann weißt du das der erste String im Array-args der zu suchende Text ist.
Der zweite ist der Text, der ersteren ersetzen soll.
Alle weiteren Strings in args geben die Dateinamen/pfade an, von den Dateien, welche behandelt werden sollen.

Das heißt du gehst von einem Nutzer aus, der weiß wie er das Programm zu starten hat und dir gleich alle Informationen die du benötigst - wie tagedieb bereits sagte - von Beginn an mitliefert.
 

RelaX

Aktives Mitglied
ok, ich danke euch für die nette Hilfe..

Jetzt schau ich mal was ich damit anfangen kann... Echt Spitze.. wäre darauf wirklich nie gekommen.. Aber naja wenigstens hab ich jetzt ein Programm das nciht ganz umsonst war ;-)

Ich meld mich wenn ich soweit bin.. Danke euch wirklich
 

RelaX

Aktives Mitglied
So ich hab das jetzt mal gemacht wie ihr gesagt habt und das ist jetzt bei rausgekommen.

Code:
public class Replace
{
    String suchstring;
    String ersetzungsstring;

    public Replace(String suchstring, String ersetzungsstring) {

        this.suchstring = suchstring;
        this.ersetzungsstring = ersetzungsstring;
    }

    public static void main(String[] args) throws IOException {

        String suchstring = args[0];
        String ersetzungsstring = args[1];
        for (int i = 2; i < args.length; i++) {
            String objekt = args[i];
            boolean test = false;

            // file einlesen
            FileReader fileReader = new FileReader(new File(objekt));
            BufferedReader in = new BufferedReader(fileReader);
            String s = in.readLine();
            // text suchen und ersetzen und in temp file speichern
            File out = new File(objekt);
            try {
                FileWriter ausgabe = new FileWriter(out);
                BufferedWriter raus = new BufferedWriter(ausgabe);
                test = suchstring.equals(ersetzungsstring);

                while ( s != null ) {
                    raus.write(s.replace(suchstring, ersetzungsstring) + "\n");
                    System.out.println(s.replace(suchstring, ersetzungsstring));
                    s = in.readLine();
                }
                raus.close();
                ausgabe.close();
                // original mit temp file ersetzen
            }
            catch (IOException e) {
                System.err.println(e.toString());
                in.close();
                fileReader.close();

            }
        }
       
    }
}

funktioniert super. der ersetzt auch direkt die Dateien wunderbar.

Hat jemand eine idee wie ich das equals da richtig einbauen könnte?

LG
RelaX
 

tagedieb

Top Contributor
Du liest und schreibst in die gleiche Datei zur selben Zeit? Es ueberrascht mich, dass das funktioniert. Ich haette vermutet du musst zum Schreiben eine Temp Datei erstellen und am Schluss die Original Datei ueberschreiben.

Was soll das 'equals' bewirken? Wenn du 'nur' die Aufgabenkriterien pruefen willst

- Suchstring und Ersetzungsstring müssen nichtleer und verschieden sein.

dann solltest du das am Anfang ueberpruefen.



Du solltest auch einen 'finally' block nach dem 'catch' block einfuegen, welcher unabhaengig ob Fehler geworfen werden die in- und outfiles schliesst.

Ausserdem sollst du gemaess Aufgabenbeschreibung eigene Ausnahmenklassen verwenden. (Ich mag diese verdeutschten Begriffe nicht). Also musst du noch eine eigene Exception implementieren. Logisch waere eine 'ReplaceException', welche du wirfst nachdem du das Fehlerhandling abgeschlossen hast. Oder um die Inputparameter zu validieren.


Dies ist optional, aber es ist guter Stiel die main Methode so kurz wie moeglich zu halten und die Basis Funktionalitaet in eine eigene Methode auszulagern. z.B..
Java:
public void replace(String suchstring, String ersetzungsstring, String[] dateien) throws ReplaceException { ... }

Der Hintergrund ist du koenntest die Klasse ja auch aus einem andern Program aufrufen. z.B. wenn du spaeter ein GUI fuer dein Program baust kannst du nur die entsprechenden Parameter uebergeben.

PS. Java Code solltest du mit den
HTML:
[code=Java][/code]
Tags setzen, dann wird auch alles huebsch eingefaerbt
 

RelaX

Aktives Mitglied
ok werd ich in Zukunft so machen mit den
Code:
[code=Java]
[/CODE] ;-)

Wieso das lesen und schreiben gleichzeitig geht? Mach ich doch glaub ich garnicht oder? Ich lese zuerst ein, dann ist der string1 ja im Readfile wenn der nächste string2 erst ins ReadBuffer Zeitgleich mit der ausgabe des korrigierten String1 in den Writebuffer und in der Zeit wo Strin1 in den dann in den FileWriter kommt folgt String3 schon in den Readbuffer.

hoffe ich hab meine Denkweise einigermaßen gut rüber gebracht. Und noch mehr hoffe ich dass das auch wirklich so ist ;-)

falls nciht brauch ich unbedingt eine erklärung weil dann hät ich ja was gemacht was funktioniert aber auf das ich irgendwie gekommen bin obwohl ichs nicht verstehe.. hää??? Ist da wirklich Potential??
 

RelaX

Aktives Mitglied
Na equals überprüft doch den String den ich eingegeben habe auf die Korektheit. Wenn ich dafür (suchstring == ersetzungsstring) benutze kommt nicht immer das richtige raus.. hab ich zumindest mal gelesen.

Mhh ich schau mal wie ich das noch besser und am besten direkt am anfang prüfen kann denn Suchstring und Ersetzungsstring bekommen ja erst in der schleife einen wert zugewiesen. wie soll ich das denn aendern? Das schmeißt ja alles nochmal durcheinander...

Ich hab doch die methoden X.close(); der schließt mir doch alle Writer bzw Reader die ich initialisiert habe sonst würde ja die ganze zeit ein Javaprozess auf die datei verweisen und das tut es nur wenn ich die x.close(); wegmache.
hat sich erledigt.. ich war zu schnell mitm lesen. werd das noch machen mit den finaly :)

Das mit der Ausnahmeklasse muss ich noch ordentlich googlen denn sowas hab ich auch noch nie gemacht :-(

Danke dir für deine tatkräftige Unterstützung. Das Forum ist echt spitze. Gerade für mich der alleine in einer eigentlich 2 Mann Gruppe ist.

Danke danke!!!
 
Zuletzt bearbeitet:

tagedieb

Top Contributor
Die Laenge der Strings, die du liest und die Laenge der Strings die du schreibst muessen ja nicht gleich lang sein.
z.B. Ersetze 'und' durch 'ein sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr langer String'.

Logisch gesehen wuerdest du bereits Teile des Inputfiles ueberschreiben, die du noch gar nicht verarbeitet/gelesen hast.
Ich denke es haengt vom Betriebssystem ab und es wird ein neues File an einer anderen Stelle auf der Festplatte erstellt, deswegen kann man auch das alte File immer noch lesen und verarbeiten. Es wird dann einfach der Index des Festplatten directories auf die neue Datei referenziert.

Wuerde mich interessieren ob deine Loeseung auf allen Betriebsystemen (Windows, Linux, UNIX, Mac) funktioniert. Logisch gesehen ist das gleichzeitige sequentielle lesen und schreiben desselben Files ein Fehler. (Sofern mich hier nicht jemand eines besseren belehrt)
 

tagedieb

Top Contributor
RelaX hat gesagt.:
Na equals überprüft doch den String den ich eingegeben habe auf die Korektheit.

Wie gesagt ich verstehe nicht genau welche 'Korrektheit' du hier pruefen moechtest. Wenn du vergleiche willst ob 2 Strings denselben gleich sind ist
Code:
suchstring.equals(ersetzungsstring)
korrekt.

Code:
suchstring == ersetzungsstring
sollte nicht verwendet werden, da == nur auf identitaet prueft. Zwei Objekte koennen aber trotzden gleich sein - muessen aber nicht identisch sein.

Suchstring und Ersetzungsstring bekommen ja erst in der schleife einen wert zugewiesen

Ich verstehe nicht was du meinst, die beiden Werte werden dir doch wie bereits besprochen in der main Methode uebergeben. Verwechselst du hier eventuel irgendwas?
 

RelaX

Aktives Mitglied
Ja wwomöglich hast du recht ich glaub da hab ich was durcheinender gebracht was die Klasse File angeht die im Paket java.io ist. Die Klasse File kann als Absatraktion einer Datei oder eines Verzeichnisses angesehen werden. File kann sowohl absolute als auch relative Namen unter Unix und Dos/windows(unc und laufwerkbuchstaben) repräsentieren. Deswegen funktioniert das mit der Performencerhöhung sogut denn sobald ich das richtig gelesen habe arbeitet das Programm schneller... naja getestet hab ichs jetzt noch nciht.

zu deinem 2ten beitrag muss ich noch etwas googlen.
 

Neue Themen


Oben