substring entfernt zuviele Zeichen

Hallo Leute,

bin neu hier
und stehe von einem Problem dar für das ich noch keine Lösung gefunden habe.
Und zwar Lese ich Zeilenweise eine TXT-Datei, diese wird dann zeilenweise in eine ArrayList<String> gespeichert. Die wie folgt aussieht
Java:
    Adresse Hex	Hex	ASCII
	$F03800 00 00 20 20 20 20 20 20 	..      
	$F03808	20 20 20 20 20 20 20 20 	        
	$F03810	20 20 20 20 20 20 20 20 	        
	$F03850	20 20 00 00 00 00 00 00 	  ......
	$F03858	00 00 00 00 00 00 00 00 	....AB..
	$F03860	00 00 00 00 00 00 00 00 	.....JK.
	$F03868	00 00 00 00 00 00 00 00 	...@.&.
	$F03870	00 00 00 00 00 00 31 32 	......12

Die ArrayList wird dann weiter verarbeitet und zwar wird jede einzelne Zeile in zwei einzelne Strings zerlegt und in eine Map<String, String> hinterlegt damit es zum Schluss so aussieht: keymap=0xF03800 (Adresse) und valuemap=0000202020202020 (Daten) usw.
Hier der Code dazu:
Java:
 ...// TXT-Datei einlesen und in eine ArrayList packen..
for (int i = 0; i < list.size(); i++) {
			//System.out.println(list.get(i));
			if (list.get(i).toString().startsWith("$"))
				// Nur die Zeilen die eine Adresse beinhalten
				str = list.get(i).toString();
			if (str.indexOf("$") == 0) {

				/*
				 * das ursprüngliche Dollarzeichen "$" wird durch "0x" ersetzt
				 */

				str2 = (str.substring(0, str.lastIndexOf(" "))).replace("$",
						"0x");
				
				keyMap = str2.substring(0, str2.indexOf("\t")).trim();
				
				valueMap = str2.substring(str2.indexOf("\t"));
				valueMap = valueMap.trim().replaceAll(" ", "");
				txtProtocol.put(keyMap, valueMap);
			}

		}// end for

Nun zum Problem, wenn die TXT-Datein so aussieht wie in Zeile 3&4 d.h. nach den Daten keine anderen Zeichen mehr kommen, löscht die substring()-Methode (Zeile 18) die letzten zwei Zeichen (20 20 20 20 20 20 20 20 wird zu 20 20 20 20 20 20 20). Da ich später aus den Daten noch die CRC Berechne wird das Ergebnis deswegen verfälscht.
Da ich bis jetzt noch keine Lösung für dieses Verhalten habe, hoffe ich, das eine von euch mir ein Paar Tipps geben kann wie ich das Problem umgehen kann.

Gruß
der neugirige

PS. war nicht so schnell 😉
 
Zuletzt bearbeitet:
Hallo,

wenn ich es richtig verstehe, was du vor hast, dann solltest du einfach die Zeichen abzählen und nicht nach einen bestimmten Zeichen suchen lassen.

Statt
Java:
str2 = (str.substring(0, str.lastIndexOf(" "))).replace("$",
                        "0x");
machst du einfach
Java:
str2 = (str.substring(0, 31)).replace("$","0x");
(Hoffe ich habe mich nicht verzählt.)
Ich gehe mal davon aus, daß die Adresse immer 7stellig ist, gefolgt von 8 2stelligen Werten getrennt durch ein Tab oder Leerzeichen.

MfG
hansmueller
 
Irgendwelche Orientierungspunkte wird es ja geben. Ist denn alles variabel?
Können denn Adressen mit mehr oder weniger als 8 Byte belegt sein?
Kann man eventuell an der Kopfzeile erkennen wie die Datei aufgebaut ist?
 
> Nun zum Problem, wenn die TXT-Datein so aussieht wie in Zeile 3&4 d.h. nach den Daten keine anderen Zeichen mehr kommen, löscht die substring()-Methode (Zeile 18) die letzten zwei Zeichen

steht denn zwischen all den 20 auch jeweils ein Tab? ansonsten kommt es gar zur Exception, weil str2.indexOf("\t") dann -1 liefert

und in meinem lokalen Test wird in Zeile 12 schon die letzte 20 abgeschnitten, eben weil zwischen den 20 eher Leerzeichen stehen statt Tab,
wenn nirgendwo Leerzeichen sind, dann hast du mit Zeile 12, die nach Leerzeichen such, generell Probleme

du solltest erklären wo wann Leerzeichen oder Tabs oder sonstiges stehen,
am besten immer vollständige Test-Programme posten, unabhängig von Dateien, alles im Programm definiert:
Java:
public class Test
{
    public static void main(String[] args)
    {
        // String str = "$F03808 20 20 20 20 20 20 20 20\t   rr ";
        String str = "$F03808 20 20 20 20 20 20 20 20";
        
        String str2 = str.substring(0, str.lastIndexOf(" "));
        System.out.println("str2: " + str2);
        String keyMap = str2.substring(0, str2.indexOf("\t")).trim();
        String valueMap = str2.substring(str2.indexOf("\t"));
        valueMap = valueMap.trim().replaceAll(" ", "");
        System.out.println(keyMap + " - " + valueMap);
    }
}
hab das Programm schon vereinfacht, $ zu 0x scheint ja kein Problem zu sein,
statt 7-8x 20 wären auch unterschiedliche Werte, z.B. 21, 22, 23, 24 usw. übersichtlicher 😉

-----

du sagst dass der String eine variable Länge hat, wo Leerzeichen oder Tab auftauchen scheint mir zumindest noch unbekannt,
die Zeile endet mal so, mal so..
gibt es denn überhaupt irgendwelche Regeln, nach denen man sich richten kann?
willst du auch Strings der Form "$hallo 3 4 5" parsen oder nicht, was genau sind die Eckdaten?
kann man immer davon ausgehen, dass in der Mitte nur zwei-ziffrige Zahlen mit Tab oder Leerzeichen dazwischen stehen?
wie viele, sind es immer 8 oder auch weniger, wenn weniger kann dann am Ende noch " ......" folgen, oder das nur wenn auch 8 Ziffernpaare vorhanden sind?
dann würde ich sagen, dass du doch wieder mit Länge arbeiten kannst, wenn < 31, dann ein Ende a la " ......" ignorieren, ansonsten ist 0-31 der Key und der Rest wird separat als Value angeschaut,
oder ist links von den 8 Ziffernpaaren auch was variabel?

usw., du musst entweder
a) alle relevanten Details exakt darlegen
oder
b) eine Menge bisher bekannter Beispiele geben (als String in Java kodiert, nicht aus unbekannter Datei mit Leerzeichen oder Tabs)
und wie diese interpretiert werden sollen,
dann kann man zumindest Regex/Suche/subString zusammenstellen, die mit genau allen diesen Beispielen klarkommen,

bisher wäre es str.substring(0, 31), du sagst dass das nicht geht weil variabel, gibst aber weder Alternativ-Beispiele noch genaue Regeln
 
Das sind immer 8 Byte pro Zeile?

Java:
import java.util.regex.*;
[...]
Pattern p = Pattern.compile("\\$(\\w{6})((:?\\W\\w{2}){8})");
Matcher m = p.matcher("");

for (String line : strings) {
	m.reset(line);
	if (m.find()) {
		txtProtocol.put("0x" + m.group(1), m.group(2).replace(" ", ""))
	}
}
 
Hallo,

erstmal Danke an alle.

@Michael
Die Adressen sind immer konstant, d.h.: 3 Byte lang
Die Daten sind variabel von min. 2 Byte bis max. 8 Byte.
Nach den Daten kommt die ASCII Interpretation der Daten und die können alle möglichen Zeichen enthalten.

@SlaterB

Sorry da war ich zu schnell Unterwegs,

Die TXT-Datei ist eine Art Log-Datei die mit Hilfe eines zusätzlichen Geräts auf ein Multimediagerät
zugreift und seinen Speicher samt den Inhalt abspeichert. -Auf die Log-Datei habe ich nur bedingt Einfluss.

hier der Aufbau der relevanten Zeilen nach Notepad++:
Java:
$F00300	00 06 07 32 33 D6 C2 	...23..
 "tab"$F00300"tab"00"lz"06"lz"07"lz"32"lz"33"lz"D6"lz"C2"lz""tab""ASCII Interpretation"
lz = leerzeichen, für die Ascii Interpretation kann alles Möglich drin stehen, eben die ASCII Zeichen

das mit den lauten 20 im ersten Post steht so in der Datei drin. Die txt selbst hat über 200 relevanten Zeilen.

@fjord
siehe oben

Gruß
 
dein Format widerspricht ein wenig einer Aussage
> löscht die substring()-Methode (Zeile 18) die letzten zwei Zeichen

wie sollte das vor sich gehen? wenn kein Tab dazwischen, dann kann ja auch nichts zerschnitten werden, oder vermutest du unbekannte Faktoren?
subString arbeitet aber deterministisch und nachvollziehbar,
schau dir den eingelesenen String an, gib ihn Zeichen für Zeichen aus, teste ob == '\t' usw,
dann schaue nach was str2.indexOf("\t") als Zahl ergibt und dann weist du wo genau abgeschnitten wird

------

wie auch immer, Vorschlag ist nach wie vor:
schaue nach ob der String länger oder kürzer als 31 Zeichen ist, wenn länger, dann gibt es einen Abschnitt hinter den 8 2er-Paaren,
wenn nicht dann nicht,
mit einer solchen Unterscheidung sollten wenigen Fehler auftreten
 
@SlaterB

es ist kein TAB zwischen den Daten nur Leerzeichen, erst wenn die Daten zu ende sind kommt ein Leerzeichen gefolgt von einem TAB plus die ASCII Interpretation. Bei den Problem Zeilen aus Post eins
kommt nach den Daten Leerzeichen + TAB + "mehrere Leerzeichen" da die ASCII Interpretation von 20 eben Leerzeichen sind.

werde deinen Vorschlag mit ==\t mal austesten.

Gruß
 
Bei meinem Vorschlag kann man die Anzahl der Bytes natürlich auch noch variabel machen. Dafür muss nur {8} mit {1,8} ersetzt werden und er erkennt 1-8 Bytes.
 
Hallo,

hab mal wieder Zeit euch zu berichten.


@SlaterB

habe es getestet, das Ergebnis war wie erwartet, keine TABS zwischen
den eigentlichen Daten, nur Leerzeichen. TABs sind nur vor und danach.

@fjord

dein Lösungsvorschlag, funktioniert super :applaus:.
Zwar steige ich noch nicht so richtig dahinter wie es funktioniert
aber Hauptsache es tut was es tun soll 🙂

@all
Aber warum jetzt die Substring()-Methode die letzten 2 Zeichen abschneidet ist mir immer noch
schleierhaft.

Gruß
 
schleierhaft ist mir allein, warum du nicht das vollkommen deterministische Verhalten untersuchst,
den String aus Datei ins Testprogramm zu posten ist sicherlich nicht so leicht, da können z.B. Tags verschwinden (auch wenn du das nicht mehr hören magst 😉 )

was aber lockerleicht geht, ist ein Programm zu schreiben, welches die Datei einliest und eine Ausgabe produziert wie folgt:
bearbeite Zeile: ... + Zeile + Länge
Zeichen 1 ist: .. + Zeichen, + ASCII-Code des Zeichens
Zeichen 2 ist: .. + Zeichen, + ASCII-Code des Zeichens
........ bis letztes Zeichen
str.lastIndexOf(" ") ist = ..
str2 = ..., Länge ..,
str2.indexOf("\t") ist = ..
keyMap = ..., Länge ...
 

Zurück
Oben