33

I have a java string, which has a variable length.

I need to put the piece "<br>" into the string, say each 10 characters.

For example this is my string:

`this is my string which I need to modify...I love stackoverlow:)`

How can I obtain this string?:

`this is my<br> string wh<br>ich I nee<br>d to modif<br>y...I love<br> stackover<br>flow:)`

Thanks

Anish Gupta
  • 2,218
  • 2
  • 23
  • 37
JuanDeLosMuertos
  • 4,532
  • 15
  • 55
  • 87
  • also, see https://stackoverflow.com/questions/4169699/string-manipulation-insert-a-character-every-4th-character – Ilya Serbis Oct 21 '21 at 23:39

12 Answers12

55

Try:

String s = // long string
s.replaceAll("(.{10})", "$1<br>");

EDIT: The above works... most of the time. I've been playing around with it and came across a problem: since it constructs a default Pattern internally it halts on newlines. to get around this you have to write it differently.

public static String insert(String text, String insert, int period) {
    Pattern p = Pattern.compile("(.{" + period + "})", Pattern.DOTALL);
    Matcher m = p.matcher(text);
    return m.replaceAll("$1" + insert);
}

and the astute reader will pick up on another problem: you have to escape regex special characters (like "$1") in the replacement text or you'll get unpredictable results.

I also got curious and benchmarked this version against Jon's above. This one is slower by an order of magnitude (1000 replacements on a 60k file took 4.5 seconds with this, 400ms with his). Of the 4.5 seconds, only about 0.7 seconds was actually constructing the Pattern. Most of it was on the matching/replacement so it doesn't even ledn itself to that kind of optimization.

I normally prefer the less wordy solutions to things. After all, more code = more potential bugs. But in this case I must concede that Jon's version--which is really the naive implementation (I mean that in a good way)--is significantly better.

cletus
  • 616,129
  • 168
  • 910
  • 942
  • I'm getting: Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ ) for "(.{1,10}\s+" – Boris Pavlović Feb 11 '09 at 15:04
  • Fixed it. It should've been \\s but I'd mistakenly assumed you wanted to break on word boundaries. You don't so the above should work and is much easier. – cletus Feb 11 '09 at 15:05
39

Something like:

public static String insertPeriodically(
    String text, String insert, int period)
{
    StringBuilder builder = new StringBuilder(
         text.length() + insert.length() * (text.length()/period)+1);

    int index = 0;
    String prefix = "";
    while (index < text.length())
    {
        // Don't put the insert in the very first iteration.
        // This is easier than appending it *after* each substring
        builder.append(prefix);
        prefix = insert;
        builder.append(text.substring(index, 
            Math.min(index + period, text.length())));
        index += period;
    }
    return builder.toString();
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    fantastic! and what about if I do not want to put
    within words? for example avoiding things like: stackover
    flow and putting directly
    at the end of the word?
    – JuanDeLosMuertos Feb 11 '09 at 15:09
  • 2
    Then that's a significantly harder problem. A regular expression *may* be the best way there, but you'd need to state the requirements *very* precisely first. – Jon Skeet Feb 11 '09 at 15:14
  • 1
    a short version of your code with regex in this post.. http://stackoverflow.com/questions/10530102/java-parse-string-and-add-line-break-every-100-characters – mtk Feb 26 '15 at 11:59
  • @Giancarlo if you do not want to break within the word, then you can probably just run a simple for loop and keep track of number of character after which you need to insert a `
    ` and insert it if only the current character is a `space`, or else move till the first space character and insert the `
    `
    – mtk Feb 26 '15 at 12:01
  • @mtk: This question was asked over 6 years ago. I *suspect* the OP has moved on from this issue now :) – Jon Skeet Feb 26 '15 at 12:55
  • @JonSkeet Oh yes, i didn't realize.. :) – mtk Feb 26 '15 at 13:22
22

I got here from String Manipulation insert a character every 4th character and was looking for a solution on Android with Kotlin.

Just adding a way to do that with Kotlin (you got to love the simplicity of it)

val original = "123498761234"
val dashed = original.chunked(4).joinToString("-") // 1234-9876-1234
Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124
15

You can use the regular expression '..' to match each two characters and replace it with "$0 " to add the space:

s = s.replaceAll("..", "$0 "); You may also want to trim the result to remove the extra space at the end.

Alternatively you can add a negative lookahead assertion to avoid adding the space at the end of the string:

s = s.replaceAll("..(?!$)", "$0 ");

For example:

String s = "23423412342134"; s = s.replaceAll("....", "$0<br>"); System.out.println(s);

Output: 2342<br>3412<br>3421<br>34

Kashif Ibrahim
  • 183
  • 1
  • 8
3

If you don't mind a dependency on a third-party library and don't mind regexes:

import com.google.common.base.Joiner;

/**
 * Splits a string into N pieces separated by a delimiter.
 *
 * @param text The text to split.
 * @param delim The string to inject every N pieces.
 * @param period The number of pieces (N) to split the text.
 * @return The string split into pieces delimited by delim.
 */
public static String split( final String text, final String delim, final int period ) {
    final String[] split = text.split("(?<=\\G.{"+period+"})");
    return Joiner.on(delim).join(split);
}

Then:

split( "This is my string", "<br/>", 5 );  

This doesn't split words at spaces but the question, as stated, doesn't ask for word-wrap.

Community
  • 1
  • 1
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
3

To avoid chopping off the words...

Try:

    int wrapLength = 10;
    String wrapString = new String();

    String remainString = "The quick brown fox jumps over the lazy dog The quick brown fox jumps over the lazy dog";

    while(remainString.length()>wrapLength){
        int lastIndex = remainString.lastIndexOf(" ", wrapLength);
        wrapString = wrapString.concat(remainString.substring(0, lastIndex));
        wrapString = wrapString.concat("\n");

        remainString = remainString.substring(lastIndex+1, remainString.length());
    }

    System.out.println(wrapString); 
1

I've unit tested this solution for boundary conditions:

public String padded(String original, int interval, String separator) {
    String formatted = "";

    for(int i = 0; i < original.length(); i++) {
        if (i % interval == 0 && i > 0) {
            formatted += separator;
        }
        formatted += original.substring(i, i+1);
    }

    return formatted;
}

Call with:

padded("this is my string which I need to modify...I love stackoverflow:)", 10, "<br>");
Qarj
  • 21
  • 3
1
StringBuilder buf = new StringBuilder();

for (int i = 0; i < myString.length(); i += 10) {
    buf.append(myString.substring(i, i + 10);
    buf.append("\n");
}

You can get more efficient than that, but I'll leave that as an exercise for the reader.

Lii
  • 11,553
  • 8
  • 64
  • 88
DJClayworth
  • 26,349
  • 9
  • 53
  • 79
  • Missing a trailing paren on the first append, also goes out of the string bounds – Stephen Feb 11 '09 at 15:07
  • You should probably use StringBuilder not StringBuffer. – cletus Feb 11 '09 at 15:08
  • For big Strings it might be a good idea to set the initial size of the StringBuffer/StringBuilder to (myString.length()*1.1) this way resizing the internal buffer will be avoided. – Joachim Sauer Feb 12 '09 at 12:15
  • This solution is missing an end parenthesis and throws an OutOfBoundException if myString.length() is not perfectly divisible by 10. I see someone else already mentioned this. However, no one mentioned that this can be more efficient by evaluating myString.length() before the loop, not every single loop. – Mira_Cole Feb 23 '18 at 15:41
0

The following method takes three parameters. The first is the text that you want to modify. The second parameter is the text you want to insert every n characters. The third is the interval in which you want to insert the text at.

private String insertEveryNCharacters(String originalText, String textToInsert, int breakInterval) {
    String withBreaks = "";
    int textLength = originalText.length(); //initialize this here or in the start of the for in order to evaluate this once, not every loop
    for (int i = breakInterval , current = 0; i <= textLength || current < textLength; current = i, i += breakInterval ) {
        if(current != 0) {  //do not insert the text on the first loop
            withBreaks += textToInsert;
        }
        if(i <= textLength) { //double check that text is at least long enough to go to index i without out of bounds exception
            withBreaks += originalText.substring(current, i);
        } else { //text left is not longer than the break interval, so go simply from current to end.
            withBreaks += originalText.substring(current); //current to end (if text is not perfectly divisible by interval, it will still get included)
        }
    }
    return withBreaks;
}

You would call to this method like this:

String splitText = insertEveryNCharacters("this is my string which I need to modify...I love stackoverlow:)", "<br>", 10);

The result is:

this is my<br> string wh<br>ich I need<br> to modify<br>...I love <br>stackoverl<br>ow:)

^This is different than your example result because you had a set with 9 characters instead of 10 due to human error ;)

Mira_Cole
  • 763
  • 6
  • 13
0

How about 1 method to split the string every N characters:

public static String[] split(String source, int n)
{
    List<String> results = new ArrayList<String>();

    int start = 0;
    int end = 10;

    while(end < source.length)
    {
        results.add(source.substring(start, end);
        start = end;
        end += 10;
    }

    return results.toArray(new String[results.size()]);
}

Then another method to insert something after each piece:

public static String insertAfterN(String source, int n, String toInsert)
{
    StringBuilder result = new StringBuilder();

    for(String piece : split(source, n))
    {
        result.append(piece);
        if(piece.length == n)
            result.append(toInsert);
    }

    return result.toString();
}
Tim Frey
  • 9,901
  • 9
  • 44
  • 60
0

Kotlin Regex version:

fun main(args: Array<String>) {    
    var original = "this is my string which I need to modify...I love stackoverlow:)"
    println(original)
    val regex = Regex("(.{10})")
    original = regex.replace(original, "$1<br>")
    println(original)
}

Kotlin Playground

Innova
  • 1,751
  • 2
  • 18
  • 26
0
String s = // long string
String newString = String.join("<br>", s.split("(?<=\\G.{10})"));

No final <br> is added if s length is multiple of 10.

Thanks to @cletus and this answer for the inspiration

Rorrim
  • 190
  • 2
  • 7