我可以用番石榴包装文字到一个给定的宽度吗?
我希望能够将长字符串换成固定长度。 在番石榴有没有办法做到这一点?
Apache Commons / Lang的方法WordUtils.wrap(String, length)
完全符合我的需要。 番石榴有一个简单的方法来完成这个?
我知道我可以使用Splitter.fixedLength(int)
做硬包装,但我想要一个软包装。
更新:这个问题现在有了一个赏金。
很明显,Guava并没有提供这种功能,所以赏金将使用Guava中最简洁(或最完整)和Guava式的答案。 没有库存,除了番石榴允许。
我们(Guava)强烈建议您使用ICU4J的BreakIterator
类来处理在用户文本中查找断点的机制。
这是我自己的答案,以获取灵感:
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);
}
}
样本用法1 :( 80个字符的硬包装)
TextWrapper.forWidth(80)
.hard()
.wrap("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.");
输出:
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.
样本用法2 :(在60个字符或之前软包装,保留现有换行符)
TextWrapper.forWidth(60)
.respectExistingBreaks()
.wrap("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.");
输出:
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
分割一个字符串。 如果你想使用番石榴,你可以依靠Splitter.on(' ').split(string)
,但是你也必须加入结果来替换''和' n',这取决于maxLength的值。
不使用番石榴,你也可以做你想做的。 几行代码, 没有依赖关系 。 基本上,你可以使用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();
}
是的,它与原始的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 + ")");
}
}
}
所以,问题是: 你真的想用番石榴做这个吗? 与此选择相关的好处是什么?
链接地址: http://www.djcxy.com/p/64111.html