kennt Ihr eine schlaue Bibliothek für Strings, die mir ermöglichen würde, ein string in n-große Strings zu teilen und dabei den String früher zu brechen, wenn da ein Leerzeichne vorgekommen ist.
So sieht es bei mir aus, aber vielleicht gibt es da Fehler die ich nicht sehe, bzw. ich das Rad neu erfunden habe... Oder vielleicht kann man das einfacher/perfomanter machen? Habt Ihr Ideen?
Java:
importjava.util.ArrayList;importjava.util.List;importjava.util.logging.Logger;publicclassStringUtils{privatefinalstaticLogger LOGGER =Logger.getLogger(StringUtils.class.getName());publicstaticList<String>getSubStrings(String text,int n){List<String> list =newArrayList<String>();String s =newString(text);while(s.length()!=0){
s = s.trim();int end = n < s.length()? n : s.length();String sub = s.substring(0, end);int nextIndex = end;int lastIndexOfSpace = sub.lastIndexOf(" ");// index of space characterif(lastIndexOfSpace >0){
end = lastIndexOfSpace;
sub = s.substring(0, end);
nextIndex = end +1;}
list.add(sub);
s = s.substring(nextIndex);}
LOGGER.info(text);
LOGGER.info(list.toString());return list;}}
und die Testklasse dazu:
Java:
importstaticorg.junit.Assert.*;importjava.util.List;importorg.junit.Test;publicclassSimpleTestCase{@Testpublicvoidtest(){String text ="lalalla lalall ll lalal lallalhzh";int n =5;List<String> list =StringUtils.getSubStrings(text, n);assertEquals(7, list.size());}}
Als erstes [c]new StringBuilder(completeString);[/c] und dann darauf die ganzen [c]substring()[/c] Methoden aufrufen. Vorher evtl. noch alle Leerzeichen daraus entfernen.
int lastIndexOfSpace = sub.lastIndexOf(" ");// index of space characterif(lastIndexOfSpace >0){
end = lastIndexOfSpace;
sub = s.substring(0, end);
nextIndex = end +1;}
Der Teil ist bei dir wohl recht nutzlos, da du vorher sagst:
Ich stand auch mal vor der Problemstellung und habe mir etwas selbst geschrieben.
Java:
publicfinalclassUtil{publicfinalstaticString NEW_LINE =System.getProperty("line.separator");publicfinalstaticchar SPACE =' ';publicfinalstaticchar ELLIPSIS ='\u2026';privateUtil(){}/**
* Gibt einen Text umbrochen aus.
* Beruecksichtigt wird, dass Woerter moeglichst nicht umbrochen werden.
* Als Trennzeichen wird nur das normale Leerzeichen (<tt>\u0020</tt>) erkannt.
* Passt der Text nicht in die angegebene Zeilenanzahl, so wird dies durch Auslassungspunkte (<tt>\u2026</tt>) am Ende gekennzeichnet.
* @param toWrap Der zuumbrechende Text.
* @param maxChars Die maximale Anzahl an Zeichen pro Zeile.
* @param maxLines Die maximale Anzahl an Zeilen, die der umbrochene Text haben soll.
* @return Den umbrochenen Text oder <tt>null</tt>, wenn <tt>toWrap == null</tt>.
* @throws IllegalArgumentException Wenn <tt>maxChars <= 0</tt>.
*/publicstaticStringwrap(finalString toWrap,finalint maxChars,finalint maxLines){if(maxChars <=0)thrownewIllegalArgumentException("maxChars was "+ maxChars +" but must be > 0");if(toWrap ==null)returnnull;finalString[] words = toWrap.split(SPACE +"+");finalStringBuilder builder =newStringBuilder();int lineLength =0;int lineNumber =0;for(int i =0; i < words.length; i++){if(lineLength == maxChars){if(lineNumber < maxLines -1){
builder.append(NEW_LINE);
lineNumber++;
lineLength =0;}else{
builder.deleteCharAt(builder.length()-1);
builder.append(ELLIPSIS);break;}}finalString currentWord = words[i];finalint wordLength = currentWord.length();if(wordLength + lineLength < maxChars){if(lineLength !=0){
builder.append(SPACE);
lineLength++;}
builder.append(currentWord);
lineLength += wordLength;}else{if(lineLength ==0){if(wordLength == maxChars){
builder.append(currentWord);
lineLength = wordLength;}else{
builder.append(currentWord.substring(0, maxChars));
words[i]= currentWord.substring(maxChars);
lineLength = maxChars;
i--;}}else{if(wordLength <= maxChars){if(lineNumber < maxLines -1){
builder.append(NEW_LINE);
lineNumber++;
builder.append(currentWord);
lineLength = wordLength;}else{finalint difference = maxChars - lineLength;if(difference >1){
builder.append(SPACE);
builder.append(currentWord.substring(0, maxChars - lineLength -2));}
builder.append(ELLIPSIS);break;}}else{if(maxChars - lineLength >1){
builder.append(SPACE);
lineLength++;finalint cutIndex = maxChars - lineLength;
builder.append(currentWord.substring(0, cutIndex));
words[i]= currentWord.substring(cutIndex);}
lineLength = maxChars;
i--;}}}}return builder.toString();}}
Ist schon recht viel Code für so eine kleine Aufgabe. Geht bestimmt auch kürzer.
Gibt auch einen String zurück und nicht eine Liste. Aber vielleicht hilfts ja weiter.
Testfälle gibts auch, nur hätten diese die maximale Zeichenanzahl pro Beitrag gesprengt. :noe:
Falls daran Interesse besteht, kann ich sie in einem weiteren Beitrag ergänzen.
Als erstes [c]new StringBuilder(completeString);[/c] und dann darauf die ganzen [c]substring()[/c] Methoden aufrufen. Vorher evtl. noch alle Leerzeichen daraus entfernen.
danke für den Code, ich kenne Deinen Anwendungsfall, den hatte ich auch. Ist in meinem Fall ein wenig anders aber Deinen Code werde ich evtl. auch gebrauchen.
Oh, sorry mein Fehler. Ich hatte in Erinnerung, dass die Methode trim() alle Leerstellen aus dem String entfernt. Von daher meinen vorherigen Post einfach ignorieren
Oh, sorry mein Fehler. Ich hatte in Erinnerung, dass die Methode trim() alle Leerstellen aus dem String entfernt. Von daher meinen vorherigen Post einfach ignorieren
Ähm, nicht alle, nur die die zu viel sind, zB am Anfang oder am Ende. In meinem Fall versuche ich die Wörter nicht zu brechen wenn es geht, deshalb "der Teil".
Einen kleinen Fehler habe ich bei mir gefunden, das mit Leerzeichne ist natürlich nur dann relevant, wenn die Stringlänge größer als n ist.
Java:
publicstaticList<String>getSubStrings(String text,int n){List<String> list =newArrayList<String>();String s =newString(text);while(s.length()!=0){
s = s.trim();int end = n < s.length()? n : s.length();String sub = s.substring(0, end);int nextIndex = end;int lastIndexOfSpace = sub.lastIndexOf(" ");// index of space characterif(n < s.length()&& lastIndexOfSpace >0){
end = lastIndexOfSpace;
sub = s.substring(0, end);
nextIndex = end +1;}
list.add(sub);
s = s.substring(nextIndex);}return list;}
Oder sieht Ihr noch andere Probleme? Bitte posten.
In StringBuilder gibt es die Methode [c]deleteCharAt()[/c]. Damit lassen sich relativ einfach alle überflüssigen Whithespaces zwischen den Wörtern entfernen - würde andauerndes [c]trim()[/c] ersetzen. Die Methode [c]substring()[/c] gibt es dort auch. Bei nochmaligem überlegen aber ist die Quelle der Ergebnisstrings aber egal, sofern du [c]String s = text;[/c] schreibst (obwohl, du könntest auch in der Methode [c]text[/c] selbst anstelle von [c]s[/c] verwenden, würdest damit aber gegen stilistische Konformitäten verstossen) aber um himmels Willen nicht [c]String s = new String(text);[/c] denn damit legst du im Zweifelsfall [c]text[/c] ein zweites mal im Heap an, statt nur die Start- und End-Pointer des Originals zu verwenden. Okay, StringBuilder verwendet zwar auch den Heap, jedoch nur vorübergehend. Dein [c]s[/c] dagegen bleibt dort, weil es im weiteren Programmverlauf durch die Instanzen der einzelnen Wörter noch verwendet wird.
Fazit: Beste Lösung - [c]String s = text;[/c]
In StringBuilder gibt es die Methode [c]deleteCharAt()[/c]. Damit lassen sich relativ einfach alle überflüssigen Whithespaces zwischen den Wörtern entfernen - würde andauerndes [c]trim()[/c] ersetzen. Die Methode [c]substring()[/c] gibt es dort auch. Bei nochmaligem überlegen aber ist die Quelle der Ergebnisstrings aber egal, sofern du [c]String s = text;[/c] schreibst (obwohl, du könntest auch in der Methode [c]text[/c] selbst anstelle von [c]s[/c] verwenden, würdest damit aber gegen stilistische Konformitäten verstossen) aber um himmels Willen nicht [c]String s = new String(text);[/c] denn damit legst du im Zweifelsfall [c]text[/c] ein zweites mal im Heap an, statt nur die Start- und End-Pointer des Originals zu verwenden. Okay, StringBuilder verwendet zwar auch den Heap, jedoch nur vorübergehend. Dein [c]s[/c] dagegen bleibt dort, weil es im weiteren Programmverlauf durch die Instanzen der einzelnen Wörter noch verwendet wird.
Fazit: Beste Lösung - [c]String s = text;[/c]
mit dem selben erfolg kann man auch den [c]text[/c] selbst verwenden, da ich durch [c]String s = text;[/c] lediglich eine Referenz auf [c]text[/c] erstelle und ändere somit das objekt das ich übergeben bekomme...
was sagst Du dazu? ich hoffe wir reden nicht komplet an einander vorbei---
So stand es bereits in meinem ersten Post und genau so war es auch gemeint. Unter Beachtung von Angry Developers Behauptung, die im übrigen vollkommen korrekt ist, ist es auch nicht wild, wenn [c]text[/c] innerhalb der Methode neu zugewiesen wird. Ist aber wg. stilistisch nicht wiklich korrekt, weil man schlicht einen Übergabe-Parameter verändert und seinen Wert innerhalb der Methode deswegen verliert. Nach Ausserhalb der Methode aber, wird [c]text[/c] nicht verändert.
nein der string wird nicht nach jedem leerzeichen gebrochen sondern nur in dem fall wenn der string bis zum nächsten leerzeichen größer als vorgegeben ist (weiß nicht ob ich mich klar ausgedrückt habe..)
nein der string wird nicht nach jedem leerzeichen gebrochen sondern nur in dem fall wenn der string bis zum nächsten leerzeichen größer als vorgegeben ist (weiß nicht ob ich mich klar ausgedrückt habe..)