Java 我可以用番石榴将文本包装到给定的宽度吗?

Java 我可以用番石榴将文本包装到给定的宽度吗?,java,guava,word-wrap,Java,Guava,Word Wrap,我想能够把一根长绳子包成一个固定的长度。有没有一种方法可以做到这一点 有一种方法可以完全满足我的需要。番石榴有一个简单的方法来实现这一点吗 我知道我可以用硬包装,但我想要软包装 更新:这个问题现在有悬赏 显然,这一功能在Guava开箱即用的产品中是不可用的,因此,赏金应该是使用Guava产品的最简洁(或最完整)和类似Guava的答案。除了番石榴外,不允许自由饮。以下是我自己的答案,以供启发: public final class TextWrapper { enum Strategy

我想能够把一根长绳子包成一个固定的长度。有没有一种方法可以做到这一点

有一种方法可以完全满足我的需要。番石榴有一个简单的方法来实现这一点吗

我知道我可以用硬包装,但我想要软包装


更新:这个问题现在有悬赏


显然,这一功能在Guava开箱即用的产品中是不可用的,因此,赏金应该是使用Guava产品的最简洁(或最完整)和类似Guava的答案。除了番石榴外,不允许自由饮。

以下是我自己的答案,以供启发:

public final class TextWrapper {

    enum Strategy implements WrapStrategy {
        HARD {

            @Override
            public String wrap(final Iterable<String> words, final int width) {
                return Joiner.on('\n')
                             .join(Splitter
                                    .fixedLength(width)
                                    .split(
                                        Joiner.on(' ').join(words)));
            }
        },
        SOFT {
            @Override
            public String wrap(final Iterable<String> words, final int width) {
                final StringBuilder sb = new StringBuilder();
                int lineLength = 0;
                final Iterator<String> iterator = words.iterator();
                if (iterator.hasNext()) {
                    sb.append(iterator.next());
                    lineLength=sb.length();
                    while (iterator.hasNext()) {
                        final String word = iterator.next();
                        if(word.length()+1+lineLength>width) {
                            sb.append('\n');
                            lineLength=0;
                        } else {
                            lineLength++;
                            sb.append(' ');
                        }
                        sb.append(word);
                        lineLength+=word.length();
                    }
                }
                return sb.toString();
            }
        }
    }

    interface WrapStrategy {
        String wrap(Iterable<String> words, int width);
    }

    public static TextWrapper forWidth(final int i) {
        return new TextWrapper(Strategy.SOFT, CharMatcher.WHITESPACE, i);
    }

    private final WrapStrategy  strategy;

    private final CharMatcher   delimiter;

    private final int           width;

    TextWrapper(final WrapStrategy strategy,
                final CharMatcher delimiter, final int width) {
        this.strategy = strategy;
        this.delimiter = delimiter;
        this.width = width;
    }

    public TextWrapper hard(){
        return new TextWrapper(Strategy.HARD, this.delimiter, this.width);
    }
    public TextWrapper respectExistingBreaks() {
        return new TextWrapper(
            this.strategy, CharMatcher.anyOf(" \t"), this.width);
    }

    public String wrap(final String text) {
        return this.strategy.wrap(
            Splitter.on(this.delimiter).split(text), this.width);
    }

}
输出:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas porttitor risu
s vitae urna hendrerit ac condimentum odio tincidunt. Donec porttitor felis quis
 nulla aliquet lobortis. Suspendisse mattis sapien ut metus congue tincidunt. Qu
isque gravida, augue sed congue tempor, tortor augue rhoncus leo, eget luctus ni
sl risus id erat. Nunc tempor pretium gravida.
Lorem ipsum dolor sit amet, consectetur adipiscing
elit.
Maecenas porttitor risus vitae urna hendrerit ac
condimentum odio tincidunt.
Donec porttitor felis quis nulla
aliquet lobortis. Suspendisse mattis sapien ut metus congue
tincidunt. Quisque gravida, augue sed congue tempor, tortor
augue rhoncus leo, eget luctus nisl risus id erat. Nunc
tempor pretium gravida.
样品用法2:(在60个字符或之前进行软包装,保持现有断线)

输出:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas porttitor risu
s vitae urna hendrerit ac condimentum odio tincidunt. Donec porttitor felis quis
 nulla aliquet lobortis. Suspendisse mattis sapien ut metus congue tincidunt. Qu
isque gravida, augue sed congue tempor, tortor augue rhoncus leo, eget luctus ni
sl risus id erat. Nunc tempor pretium gravida.
Lorem ipsum dolor sit amet, consectetur adipiscing
elit.
Maecenas porttitor risus vitae urna hendrerit ac
condimentum odio tincidunt.
Donec porttitor felis quis nulla
aliquet lobortis. Suspendisse mattis sapien ut metus congue
tincidunt. Quisque gravida, augue sed congue tempor, tortor
augue rhoncus leo, eget luctus nisl risus id erat. Nunc
tempor pretium gravida.

为什么不用番石榴就用番石榴做更简单的事?

实际上,
Splitter
类允许您使用
fixedLength()
方法进行硬包装,否则您可以根据分隔符
char
string
拆分字符串。如果您想使用番石榴,您可以依赖于(“”).split(string),但是您还必须根据maxLength值将结果替换为“\n”

不用番石榴,你也可以随心所欲。几行代码,没有依赖项。基本上,您可以使用commons-lang方法来简化它。这是我的包装方法:

public static String wrap(String str, int wrapLength) {
    int offset = 0;
    StringBuilder resultBuilder = new StringBuilder();

    while ((str.length() - offset) > wrapLength) {
        if (str.charAt(offset) == ' ') {
            offset++;
            continue;
        }

        int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);
        // if the next string with length maxLength doesn't contain ' '
        if (spaceToWrapAt < offset) {
            spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
            // if no more ' '
            if (spaceToWrapAt < 0) {
                break;
            }
        }

        resultBuilder.append(str.substring(offset, spaceToWrapAt));
        resultBuilder.append("\n");
        offset = spaceToWrapAt + 1;
    }

    resultBuilder.append(str.substring(offset));
    return resultBuilder.toString();
}
publicstaticstringwrap(stringstr,int-wrapLength){
整数偏移=0;
StringBuilder resultBuilder=新建StringBuilder();
而((str.length()-offset)>wrapLength){
如果(字符串(偏移量)=''){
offset++;
继续;
}
int spacetowrappat=str.lastIndexOf(“”,wrapLength+偏移量);
//如果下一个长度为maxLength的字符串不包含“”
if(空格拖距<偏移量){
spaceToWrapAt=str.indexOf(“”,wrapLength+偏移量);
//如果没有更多“
如果(空格拖距<0){
打破
}
}
resultBuilder.append(str.substring(offset,spacetowrappat));
resultBuilder.append(“\n”);
偏移量=间距拖距+1;
}
resultBuilder.append(str.substring(offset));
返回resultBuilder.toString();
}
是的,它非常类似于最初的commons-lang方法,但我想它更简短、更容易,并且是基于您的需要。也许,这个解决方案也比你的更有效,不是吗

我已经用你的文本测试了它,将我的结果与commons lang的结果进行了比较。这似乎有效:

public static void main(String[] args) {

    String string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n"
            + "Maecenas porttitor risus vitae urna hendrerit ac condimentum "
            + "odio tincidunt.\nDonec porttitor felis quis nulla aliquet "
            + "lobortis. Suspendisse mattis sapien ut metus congue tincidunt. "
            + "Quisque gravida, augue sed congue tempor, tortor augue rhoncus "
            + "leo, eget luctus nisl risus id erat. Nunc tempor pretium gravida.";

    for (int maxLength = 2; maxLength < string.length(); maxLength++) {
        String expectedResult = WordUtils.wrap(string, maxLength);
        String actualResult = wrap(string, maxLength);

        if (!expectedResult.equals(actualResult)) {
            System.out.println("expectedResult: \n" + expectedResult);
            System.out.println("\nactualResult: \n" + actualResult);
            throw new RuntimeException(
                    "actualResult is not the same as expectedResult (maxLength:"
                            + maxLength + ")");
        }
    }
}
publicstaticvoidmain(字符串[]args){
String=“Lorem ipsum door sit amet,concetetur adipsicing elit。\n”
+“Maecenas porttitor risus vitae urna hendrerit ac调味品”
+“odio tincidunt.\nDonec porttitor felis quis nulla aliquet”
+“lobortis.Suspendisse mattis sapien ut metus congue tincidunt”
+“怀孕女佣,临时工,侵权人”
+“利奥,我是临时孕妇。”;
对于(int maxLength=2;maxLength

所以,问题是:你真的想用番石榴来做这件事吗?这个选择有什么好处?

我这么做是为了好玩,只是为了尽可能多地吃番石榴。但javanna的答案更好

import java.util.Iterator;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;


public class SoftSplit {

    public static String softSplit(String string, int length) {
        //break up into words
        Iterable<String> words = Splitter.on(' ').split(string);

        //an iterator that will return the words with appropriate
        //white space added
        final SoftSplitIterator softIter = new SoftSplitIterator(words, length);
        return Joiner.on("").join(new Iterable<String>() {
            @Override
            public Iterator<String> iterator() {
                return softIter;
            }
        });
    }

    static class SoftSplitIterator implements Iterator<String> {
        private final int maxLength;
        private final PeekingIterator<String> words;
        private int currentLineLength;

        SoftSplitIterator(Iterable<String> words, int maxLength) {
            this.words = Iterators.peekingIterator(words.iterator());
            this.maxLength = maxLength;
        }

        @Override
        public boolean hasNext() {
            return words.hasNext();
        }

        @Override
        public String next() {
            String current = words.next();

            //strip leading spaces at the start of a line
            if(current.length() == 0 && currentLineLength == 0) {
                return "";
            }
            //nothing left after us
            if(!words.hasNext()) {
                return current;
            }
            String next = words.peek();

            if(currentLineLength + current.length() + next.length() < maxLength) {
                //this word and the next one won't put us over limit
                currentLineLength += current.length();
                return current + " ";
            } else {
                //the next word will put us over the limit 
                //add a line break
                currentLineLength = 0;
                return current + "\n";
            }
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    public static void main(String[] args) {
        String text = 
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
            "Maecenas porttitor risus vitae urna hendrerit ac condimentum " +
            "odio tincidunt. Donec porttitor felis quis nulla aliquet " +
            "lobortis. Suspendisse mattis sapien ut metus congue tincidunt. " +
            "Quisque gravida, augue sed congue tempor, tortor augue rhoncus " +
            "leo, eget luctus nisl risus id erat. Nunc tempor pretium gravida.";
        System.out.println(softSplit(text, 60));
    }
}
import java.util.Iterator;
导入com.google.common.base.Joiner;
导入com.google.common.base.Splitter;
导入com.google.common.collect.Iterators;
导入com.google.common.collect.peek迭代器;
公共类软拆分{
公共静态字符串softSplit(字符串,整数长度){
//破口大骂
Iterable words=spliter.on(“”).split(字符串);
//一个迭代器,它将返回带有适当
//添加了空白
最终SoftSplitIterator softIter=新的SoftSplitIterator(字,长度);
返回Joiner.on(“”).join(new Iterable(){
@凌驾
公共迭代器迭代器(){
返回软件;
}
});
}
静态类SoftSplitIterator实现迭代器{
私有最终整数最大长度;
私密的最后偷看迭代器单词;
专用int currentLineLength;
SoftSplitIterator(Iterable字,int maxLength){
this.words=Iterators.peek迭代器(words.iterator());
this.maxLength=maxLength;
}
@凌驾
公共布尔hasNext(){
返回words.hasNext();
}
@凌驾
公共字符串next(){
字符串current=words.next();
//在行的开始处去除前导空格
if(current.length()==0&¤tLineLength==0){
返回“”;
}
//我们一无所有
如果(!words.hasNext()){
回流;
}
String next=words.peek();
如果(currentLineLength+current.length()+next.length()