Textdatei - Zeile löschen

  • Antworten:32
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 213

15.02.2016, 10:15:27 via Website

Ich möchte aus einer Textdatei eine Zeile löschen.

Gängige Lösung scheint hierfür zu sein, dass man eine neue Datei, ein neues Array oder etwas Ähnliches anlegt und hier nur die Datensätze reinschreibt, die man nicht löschen möchte (also alle außer den zu löschenden) und diese Datenmenge dann neu abspeichert.

Könnte ich ja machen. Aber kann man das nicht einfacher? Kann man nicht zB die Tastatureingaben, die man manuell beim Löschen eines Datensatzes einer Textdatei ausführen würde, simulieren? Wenn ich zB Zeile 2 löschen möchte, könnte ich an das Ende von Zeile 1 gehen und lange genug die Entf-Taste drücken. Man löscht dann wohl vor allem das Zeichen, das für den Zeilenumbruch zuständig ist. Das dürfte ja zB einen bestimmten Hex-Code haben etc.

Dabei geschieht dann so was wie das Gegenteil der Enter-Taste, mit der man ja bekanntlich eine neue Zeile einfügen kann.

Bin ansonsten auf dieses Beispiel gestoßen, das ich zunächst für Java-Code hielt. Aber es dürfte C# sein:

List linesList = File.ReadAllLines("myFile.txt").ToList();
linesList.RemoveAt(0);
File.WriteAllLines("myFile.txt"), linesList.ToArray());

Das scheint mir doch viel einfacher zu sein. Aber geht so was auch in Java?

Danke!

— geändert am 15.02.2016, 10:17:32

Antworten
  • Forum-Beiträge: 605

15.02.2016, 10:21:13 via Website

Das ist im Prinzip dein oben beschriebenes "normales" Vorgehen.

Nur das hier nicht nur die nicht zu löschenden Zeilen eingelesen werden, sondern erst ALLE Zeilen, und die entsprechende dann gelöscht wird.

Frank Rudolf

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.174

15.02.2016, 17:42:54 via Website

Wenn ich diesen Beitrag mit deinen Vorherigen kombiniere, dann geht es hier doch um das Löschen einer Zeile aus der CSV Datei oder?
Wenn ja dann sehe ich 2 Möglichkeiten:

  1. Du weißt welche Zeile und hast die darin stehenden Daten zur verfügunf (bereitgestellt über ListView->ClickListener etc..
    Damit weisst du nach was du in der Datei suchen musst und kannst den eintrag ganz einfach per String#replace/remove löschen.

  2. Du baust dir eine Objektstruktur, sodass ein CSV File ein Objekt ist und dieses eine Liste Mit Items o.ä. enthält.
    Willst du eine Zeile löschen, dann klöscht du das Objekt aus deiner liste.
    Zum speichern schreibst du einfach eine Methode die die Liste per Schleife durchgeht und pro CsvItem eine Zeile hinzufügt.
    Dann werden die entfernten automatisch weggelassen.

Ich bevorzuge Methode 2 da ich ein Fan von Objekorientierung bin ;)

LG Pascal //It's not a bug, it's a feature. :) ;)

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

15.02.2016, 20:04:59 via Website

Hallo Pascal,

ich weiß nicht, ob ich Dich richtig verstanden habe.

In der Tat weiß ich über die ID ganz genau, welche Zeile innerhalb der CSV ich löschen möchte.

Zu 2:
Ein Objekt nützt mir wohl nichts, weil ich dadurch die zugrundeliegende CSV-Datei nicht gelöscht bekomme.

Zu 1:

Wie löscht man denn "ganz einfach" per "String#replace/remove"??? Replace kenne ich eher von Textfunktionen, remove hört sich wie eine auf eine Arraylist bezogene Methode an. Das sind aber keine Dateioperationen, oder?

Meine Idee, die mir im Laufe des Tages gekommen ist:
Ich lösche nicht wirklich, sondern markiere innerhalb meiner Textdatei. Konkrekt: ich führe eine Spalte ein, mit der ich über 1 oder 0 sage, ob diese Zeile als gelöscht oder nicht gelöscht markiert ist. Beim Laden der Datei werden die als gelöscht markieren nicht berücksichtigt.

Technisch gesehen brauche ich zum Löschen also die Datei (genauer: die jeweilige Zeile) nur zu bearbeiten (aus 0 wird eine 1 oder umgekehrt).

— geändert am 15.02.2016, 20:05:58

Antworten
Pascal P.
  • Mod
  • Blogger
  • Forum-Beiträge: 10.174

16.02.2016, 08:32:45 via App

Leider nicht..
Du musst die Datei einlesen das was du löschen willst rauswerfen und wieder speichern/ neu schreiben.
Anders geht das nicht.

Die FileHandler sind dafür zu allgemein und würden das vom Prinzip her sonst gleich machen.

— geändert am 16.02.2016, 08:35:49

LG Pascal //It's not a bug, it's a feature. :) ;)

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

16.02.2016, 09:03:44 via Website

Danke Pascal!

Leider scheint das Problem auch beim reinen Modifizieren (Ändern) von Dateiinhalten zu bestehen. Was bei anderen Sprachen wie VB.net, C## oder Java ohne Probleme geht, geht bei Android (trotz Java) scheinbar nicht so einfach.

Noch eine Alternative wäre vielleicht diese Sache mit RandomAccessFile (oder so ähnlich). Nur muss man dabei wohl immer bytegenau eine Position ansteuern. Dies dürfte bei meiner Textdatei, deren Zeilen und "Spalten" eine unterschiedliche Länge haben, aufwendig sein.

Habe gestern noch mit dem LineNumberReader herumgespielt und so übel sah das nicht aus. Mit ein paar Imports versteht Android das Vokabular.
Meist wird in den Beispielen zu Anfang eine Datei definiert, auf die zugegriffen werden soll, zB:

File myFile = new File("Test.csv");

Hier bekomme ich meinen ersten Fehler. Die Datei sei nicht vorhanden. Aber das könnte doch wohl an der falschen oder fehlenden Pfadangabe liegen.

Die Frage wäre, ob ich hier einen korrekten Dateipfad angeben könnte. data/data/[packageName]/files ... oder so ähnlich geht ja wohl nicht, weil das nur der Pfad des Emulators ist, denke ich.

Eine Möglichkeit sehe ich vielleicht noch in der Angabe eines Pfads, der auf die SDCard zugreift. Weißt Du, wie man den angeben müßte?

Was ich jedoch haben muss, ist eine leichte Möglichkeit zum gelegentlichen Austausch der alten Datei durch eine neue (ca alle zwei Wochen. Dies liegt daran, dass ich mindestens zwei solcher TextDateien synchronisieren möchte, da ich noch mit mindestens einer auf dem Desktop-PC arbeite. Es würde mir genügen, wenn ich die Text-Datei vom PC in irgendeinen Ordner auf dem Tablet (oder Smartphone) speichern könnte und das Programm würde dann auf die neue Textdatei zugreifen können. Der umgekehrte Weg (vom Tablet nehmen und auf den PC übertragen) sollte natürlich auch gehen.

Was ich hier in der Entwicklungsumgebung auf ähnliche Weise zu Testzwecken mache, genügt mir: ich gehe einfach in data/data/packagename ... und kopiere dort die neue Testdatei rein. Ab und zu kopiere ich sie mir auf den DesktopPC (damit ich überhaupt sehe, was genau in der Datei steht). Das alles geht mit dem AndroidDeviceMonitor und seinem FileManager ganz gut. Nur: das ist nur ein Emulator mit Pfadangaben, die nachher in der Praxis nicht mehr gelten - denke ich.

Ich wollte nicht zu weitschweifig werden, aber diese Backgrounds sind ja auch nicht unwichtig.

— geändert am 16.02.2016, 09:07:32

Antworten
  • Forum-Beiträge: 605

16.02.2016, 09:10:36 via Website

Soll die App nur auf deinem Gerät laufen, oder soll die später auch veröffentlicht werden?

Spätestens dann bekommst du mit der SD-Karte Probleme. Es gibt schließlich aucbh Device ohne SD-Slot, mit zwei Slots, oder mit Slot, aber der Nutzer hat keine Karte eingelegt.

Sonst ist das natürlich möglich. Schau dir dazu mal den folgenden Link an.

http://developer.android.com/guide/topics/data/data-storage.html

Wichtig ist auch, dass du die Permissions setzt.

Das weitere Vorgehen müsste, so wie von Pascal beschrieben, möglich sein.

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

16.02.2016, 09:15:56 via Website

Hallo Henrik!

Mir reicht es absolut, wenn meine aktuelle erste App nur in meinem Privatbereich läuft.

Ich werde mich wohl mit dem umständlichen Weg abfinden müssen:
Datensätze, die ich löschen oder ändern möchte, werden einfach bei einer Neuanlage der Gesamtdatei ignoriert bzw die zu ändernden werden dabei einfach neu angelegt.

Antworten
  • Forum-Beiträge: 605

16.02.2016, 09:21:01 via Website

Hallo Frank,

so umständlich ist das doch gar nicht. Du weißt ja, wo deine zu löschenden Zeilen stecken.

Erstelle dir ein eigenes Objekt, oder arbeite mit Soder besser ArrayList. Lade die Textdatei Zeile für Zeile (mit Schleife) in die ArrayList. Lösche die Zeilen die du nicht brauchst, und Schreibe die ArrayList wieder Zeile für Zeile in die Datei. Hier arbeitest du wieder mit einer Schleife.

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

16.02.2016, 09:25:28 via Website

Ja, genau. So ähnlich verfahre ich ja bereits an anderer Stelle innerhalb der app.

Antworten
  • Forum-Beiträge: 605

16.02.2016, 09:27:19 via Website

Das ist, meines Wissens, die einfachste und effektivste Lösung. Und vor Allem ist sie relativ übersichtlich und variabel. Du kannst also ohne großen Aufwand, z.B. wenn sich deine Dateistruktur ändert, die zu löschenden Zielen ändern.

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

16.02.2016, 12:01:29 via Website

So, ich bin jetzt an der Stelle, wo ich meine Textdatei "leeren" muss.

Zuvor habe ich alle Daten bis auf die zu löschenden in eine ArrayList verfrachet. Von der ArrayList wollte ich eigentlich die Daten in eine zuvor zu leerende Textdatei schreiben. Sonst stünden fast alle doppelt drin.

Jetzt gibt es mehrere Möglichkeiten:

A)
Ich schreibe alles in eine neue Textdatei. Eventuell muss ich sie dabei wieder umbennen. Da ich die ArrayList als ZwischenSpeicher habe, brauche ich eigentlich nur eine Datei. Ich weiß, dass man sowas aus Datensicherheitsgründen in der Praxis nicht machen sollte. Ich habe aber auch mindestens eine Kopie der Datei im Notfall zur Hand.

B)
Ich leere die alte Datei. Einfach "" einfügen? Zeilenweises Durchlaufen in einer Schleife und jede Zeile auf "" setzen? Da habe ich keinen Plan.

Einfacher und weniger fehlerträchtig dürfte A) sein. Da ich natürlich wieder die Befehle nicht kenne und mit der Syntax unsicher bin, würde mir ein CodeBeispiel helfen. Ich fürchte, dass ich mit der "einfachen" Methode und einer neuen zweiten Datei Probleme bekommen würde, wenn ich Pfadangaben machen müßte!

Bin jetzt für ein zwei Stunden weg.

— geändert am 16.02.2016, 12:03:26

Antworten
  • Forum-Beiträge: 605

16.02.2016, 12:05:21 via Website

Probiere es mal so:

PrintWriter writer = new PrintWriter(file);
writer.print("");
writer.close();

Damit kannst du den Inhalt der bestehenden Textdatei löschen.

Frank Rudolf

Antworten
  • Forum-Beiträge: 213

16.02.2016, 13:56:39 via Website

Ich bekomme durch

 PrintWriter writer = new PrintWriter("Test.csv");

folgendes:

java.io.FileNotFoundException: Test.csv: open failed: EROFS (Read-only
file system)

— geändert am 16.02.2016, 13:57:44

Antworten
  • Forum-Beiträge: 213

16.02.2016, 14:10:55 via Website

Ich habe wohl von 4.0.3 an aufwärts bei diesem Projekt.

— geändert am 16.02.2016, 14:11:35

Antworten
  • Forum-Beiträge: 605

16.02.2016, 14:12:57 via Website

Wichtig ist nur:

Muss ein Gerät mit 6.0 oder ggf. höher komatibel sein?

Wenn nein, dann reicht das einfache Setzten der Permission in der Manifest.

Antworten

Empfohlene Artikel