JAVA - 在30个字符后的下一个空格处插入新行

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());
}

感谢您的帮助。

那么问题是什么?这个能行吗? - Michael Myers
抱歉,它不起作用,我会编辑问题。 - Kevin Stich
3
顺便提一下,正确的大写应该是“Java”,而不是“JAVA”——但标签通常足以让人们知道你感兴趣的平台。 - erickson
6个回答

18
如kdgregory所建议的那样,使用StringBuilder可能是一种更容易处理字符串操作的方法。
由于我不确定在插入换行符之前的字符数是前一个单词还是后一个单词,我选择了在30个字符后面的单词,因为实现可能更容易。
这种方法是通过使用StringBuilder.indexOf查找当前正在查看的字符之后至少30个字符出现的" "实例来完成的。当出现空格时,StringBuilder.insert插入一个\n
(我们将假设换行符为\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 以获得期望的行为。


这个方法很完美,只需要将 sb.insert(i, "\n"); 改为 sb.replace(i, i+1, "\n"); 即可。谢谢! - Kevin Stich
@Kevin Stich:我已经更新了示例代码——在这个例子中,for循环并不是很合适,所以它被替换成了while循环。 - coobird
1
它没有按字符数限制行,例如,如果我将many更改为manyyyy,则manyyyy不会出现在下一行上。 - Leslie

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();
    }
}

3
谢谢!我喜欢先写测试代码,也喜欢推广这种做法;我想我会用这种方式写更多的回答。感谢你的鼓励。 - Carl Manaster

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();
}

我认为如果你不在while循环中递增pos,你会意外地用\n替换每个空格,导致第一行之后的所有行只有一个单词。你需要在每次替换后将pos增加30。 - Karl

1
我会遍历字符串而不是30。但你必须跟踪这个30。
伪代码,因为这听起来像作业:
charInLine=0
iterateOver each char in rawString
    if(charInLine++ > 30 && currChar==' ')
        charInLine=0
        currChar='\n'

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());

这是正确的,我也尝试过。


0

也许我漏掉了什么。这段代码有什么问题呢?

String s = ... s = s.substring(0, 30) + s.substring(30).replace(' ', '\n');

这段代码会将第30个字符之后的所有空格替换为换行符。

虽然效率略低,但对于200个字符来说,这并不重要(这在数据处理中非常小)。

Bruce


1
然后,第30个字符之后的每个单词都将在自己的一行中。 - Michael Myers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接