3

我有一大块文本(字符串中有 200 多个字符),需要在 30 个字符后的下一个空格处插入新行以保留单词。这是我现在拥有的(不工作):

String rawInfo = front.getItemInfo(name);
String info = "";
int begin = 0;
for(int l=30;(l+30)<rawInfo.length();l+=30) {
    while(rawInfo.charAt(l)!=' ')
        l++;
    info += rawInfo.substring(begin, l) + "\n";
    begin = l+1;
    if((l+30)>=(rawInfo.length()))
        info += rawInfo.substring(begin, rawInfo.length());
}

谢谢你的帮助

4

6 回答 6

18

正如 kdgregory 所建议的,使用 aStringBuilder可能是处理字符串操作的一种更简单的方法。

由于我不太确定插入换行符之前的字符数是 30 个字符之前还是之后的单词,所以我选择了 30 个字符之后的单词,因为实现可能更容易。

" "方法是使用 查找当前字符后至少 30 个字符出现的实例StringBuilder.indexOf。当出现空格时,a\n被 插入StringBuilder.insert

(我们假设\n这里有一个换行符——当前环境中使用的实际行分隔符可以通过 检索System.getProperty("line.separator");)。

这是示例:

String s = "A very long string containing " +
    "many many words and characters. " +
    "Newlines will be entered at spaces.";

StringBuilder sb = new StringBuilder(s);

int i = 0;
while ((i = sb.indexOf(" ", i + 30)) != -1) {
    sb.replace(i, i + 1, "\n");
}

System.out.println(sb.toString());

结果:

一个很长的字符串,包含许多
许多单词和字符。换行符
将要。

我应该补充一点,上面的代码尚未经过测试,除了String我在代码中显示的示例。如果它在某些情况下不起作用,那就不足为奇了。

编辑

示例代码中的循环已替换为while循环,而不是for在本示例中不太合适的循环。

此外,该StringBuilder.insert方法被该方法取代StringBuilder.replace,正如 Kevin Stich 在评论中提到的那样,该replace方法被用于insert获得所需的行为而不是 。

于 2009-06-23T16:24:15.067 回答
4

这是一个测试驱动的解决方案。

import junit.framework.TestCase;

public class InsertLinebreaksTest extends TestCase {
    public void testEmptyString() throws Exception {
        assertEquals("", insertLinebreaks("", 5));
    }

    public void testShortString() throws Exception {
        assertEquals("abc def", insertLinebreaks("abc def", 5));
    }

    public void testLongString() throws Exception {
        assertEquals("abc\ndef\nghi", insertLinebreaks("abc def ghi", 1));
        assertEquals("abc\ndef\nghi", insertLinebreaks("abc def ghi", 2));
        assertEquals("abc\ndef\nghi", insertLinebreaks("abc def ghi", 3));
        assertEquals("abc def\nghi", insertLinebreaks("abc def ghi", 4));
        assertEquals("abc def\nghi", insertLinebreaks("abc def ghi", 5));
        assertEquals("abc def\nghi", insertLinebreaks("abc def ghi", 6));
        assertEquals("abc def\nghi", insertLinebreaks("abc def ghi", 7));
        assertEquals("abc def ghi", insertLinebreaks("abc def ghi", 8));
    }

    public static String insertLinebreaks(String s, int charsPerLine) {
        char[] chars = s.toCharArray();
        int lastLinebreak = 0;
        boolean wantLinebreak = false;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            if (wantLinebreak && chars[i] == ' ') {
                sb.append('\n');
                lastLinebreak = i;
                wantLinebreak = false;
            } else {
                sb.append(chars[i]);
            }
            if (i - lastLinebreak + 1 == charsPerLine)
                wantLinebreak = true;
        }
        return sb.toString();
    }
}
于 2009-06-23T16:43:55.853 回答
3

更好的解决方案:将字符串复制到 StringBuilder 中,这样您就可以插入/更改字符而无需大量子字符串混淆。然后使用 indexOf() 方法获取起始位置来查找要更改的索引。

编辑:编码:

public static String breakString(String str, int size)
{
    StringBuilder work = new StringBuilder(str);
    int pos = 0;
    while ((pos = work.indexOf(" ", pos + size)) >= 0)
    {
        work.setCharAt(pos, '\n');
    }
    return work.toString();
}
于 2009-06-23T16:10:31.693 回答
1

我会遍历字符串而不是 30。不过,您必须跟踪 30。

伪代码,因为这听起来像家庭作业:

charInLine=0
iterateOver each char in rawString
    if(charInLine++ > 30 && currChar==' ')
        charInLine=0
        currChar='\n'
于 2009-06-23T16:27:59.593 回答
0

也许我错过了一些东西。有什么问题

字符串 s = ... s = s.substring(0, 30) + s.substring(30).replace(' ', '\n');

这会将所有空格替换为从字符 30 开始的换行符。

它的效率略低,但对于 200 个字符,它真的没关系(这对于数据操作来说非常小)。

布鲁斯

于 2009-06-23T18:43:27.297 回答
0
    String s = "A very long string containing " +
"many many words and characters. " +
"Newlines will be entered at spaces.";
StringBuilder sb = new StringBuilder(s);
int i = 0;
while ((i = sb.indexOf(" ", i + 30)) != -1) {
    sb.replace(i, i + 1, "\n");
}
System.out.println(sb.toString());

这是正确的我也试过这个。

于 2018-09-30T15:59:44.893 回答