Java Word Wrap Algorithm

On a recent coding project I’ve been working on, I had need for a simple line-wrapping method.  I googled around, but couldn’t find anything useful — so, like any coder, I made my own.  I think it’s pretty nice, if I do say so myself:

public static String wrap(String in,int len) {
in=in.trim();
if(in.length()<len) return in;
if(in.substring(0, len).contains("\n"))
return in.substring(0, in.indexOf("\n")).trim() + "\n\n" + wrap(in.substring(in.indexOf("\n") + 1), len);
int place=Math.max(Math.max(in.lastIndexOf(" ",len),in.lastIndexOf("\t",len)),in.lastIndexOf("-",len));
return in.substring(0,place).trim()+"\n"+wrap(in.substring(place),len);
}

That first “in.indexOf()” has the space string (” “) as an argument, not an empty string.

I apologize for the difficult-to-read-ness of this code; I had it nicely spaced and indented but WordPress ate my formatting.
If you want to be really fancy, switch out the “\n” with a System.getProperties(line.separator).

About these ads
  1. are you on linkedin?

    • Nate
    • August 1st, 2011

    Thanks for posting this; I was looking for a simple line wrap approach for my own code, and I didn’t even think to approach it recursively! Thanks for the inspiration!
    – Nate

    • Happy to help! I only wish I had made it before a programming competition I was in; there was one problem that required word-wrapping!

        • Nate
        • August 15th, 2011

        Hey, I ran into a (small) problem with the above algorithm; it doesn’t account for a “word” that is longer than the maximum length of a line. So, like any coder, I fixed the bug :-).

        Effectively, I made it so that if the word is too big, it’ll slice it at the
        maximum length. One other modification I made was a rewrite of the “trim” functionality; I needed to retain leading/trailing newlines in my particular application.

        Here’s the code:

        //|| wordWrap
        /**
        * Performs word wrapping. Returns the input string with long lines of
        * text cut (between words) for readability.
        *
        * @param in text to be word-wrapped
        * @param length number of characters in a line
        */
        public static String wordWrap(String in, int length) {
        //:: Trim
        while(in.length() > 0 && (in.charAt(0) == ‘\t’ || in.charAt(0) == ‘ ‘))
        in = in.substring(1);

        //:: If Small Enough Already, Return Original
        if(in.length() < length)
        return in;

        //:: If Next length Contains Newline, Split There
        if(in.substring(0, length).contains(newline))
        return in.substring(0, in.indexOf(newline)).trim() + newline +
        wordWrap(in.substring(in.indexOf("\n") + 1), length);

        //:: Otherwise, Split Along Nearest Previous Space/Tab/Dash
        int spaceIndex = Math.max(Math.max( in.lastIndexOf(" ", length),
        in.lastIndexOf("\t", length)),
        in.lastIndexOf("-", length));

        //:: If No Nearest Space, Split At length
        if(spaceIndex == -1)
        spaceIndex = length;

        //:: Split
        return in.substring(0, spaceIndex).trim() + newline + wordWrap(in.substring(spaceIndex), length);
        }

        A prettier (better-indented) version can be downloaded from the following url: http://www.mediafire.com/file/5dssy5emsr1rews/wordWrap.java

    • Nate
    • August 15th, 2011

    oh, oops. I forgot that the class I placed this function into has a static variable called “newline”:

    private static final String newline = System.getProperty(“line.separator”);

    Here’s an updated file:
    http://www.mediafire.com/file/r93a99ipwawvzxv/wordWrap.java

  2. This doesn’t cater for all the multitude of line separating conventions which are out there; Your source data might not be using the same line break convention as the platform your code is running on.

    I’ve written code which handles that case and might post it later. But the key is to recognise when a character is a line separator, indicating the start of the line break which comprises all following line separator characters which aren’t the same as the first. Consider parsing;

    * “One\n\rTwo\n\r\n\rFour (three was blank)”
    * “One\rTwo\r\rFour (three was blank)”
    * “One\nTwo\n\nFour (three was blank)”
    * “One\r\nTwo\r\n\r\nFour (three was blank)”

    … I’ve got code which works for those and more.

    • You could just repace “\n” with System.getProperty(“line.separator”), like I believe I said.

      But that is a good point!

      • That won’t work reliably, I’m afraid :-( . What if the text originates from a system where the line.separator value would be different?

        e.g. the text is from Windows, Java is running on Unix… then System.getProperty(“line.separator”) wouldn’t give you the line separator you need (nor could anything else, really).

    • Nate
    • September 15th, 2011

    That is an excellent point. Perhaps the line separator should be automatically detected? (search for the existence of the substring “\r\f”; if found, it’s probably Windows. If not found, “\n” should probably work? It’s not a clean solution, but it’s the only one I can think of.

  3. Nice one Robert, like the other guys, I just made some minor mods to suit what I needed

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: