4

您知道将文本字符扩展为空格的 java 方法吗?

我的文字:

1. <tab>  firstpoint  <tab> page  1
10. <tab> secondpoint <tab> page 10

如果我直接用 4 个空格替换制表符,我将拥有

1.    firstpoint    page1
10.    secondpoint    page2

取而代之的是,我需要一种方法来用它真正对应的空格数替换每个制表符(正如命令 :retab 的 vim 所做的那样)。有什么解决办法吗?

4

5 回答 5

5

我认为上面的 retab() 函数可能存在问题,忽略了初始选项卡。我自己做的;特此置于公有领域。

public static String expandTabs(String s, int tabSize) {
    if (s == null) return null;
    StringBuilder buf = new StringBuilder();
    int col = 0;
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        switch (c) {
            case '\n' :
                col = 0;
                buf.append(c);
                break;
            case '\t' :
                buf.append(spaces(tabSize - col % tabSize));
                col += tabSize - col % tabSize;
                break;
            default :
                col++;
                buf.append(c);
                break;
        }
    }
    return buf.toString();
}

public static String spaces(int n) {
    StringBuilder buf = new StringBuilder();
    for (int sp = 0; sp < n; sp++) buf.append(" ");
    return buf.toString();
}
于 2016-01-21T20:18:36.600 回答
4

虽然可能有一个库可以做到这一点,但手动解决方案非常简单:

  1. 创建一个输出缓冲区 ( StringBuilder)。
  2. 遍历字符串的字符
  3. 对于每个字符,检查它是否是制表符。
    一种。如果它不是选项卡,请将其添加到输出缓冲区。
    湾。如果它是一个制表符,请先添加一个空格,然后添加尽可能多的空格,以使输出缓冲区的长度可以被 4 整除。(您的制表符长度。)
  4. 返回输出缓冲区。
于 2012-07-30T13:53:25.390 回答
2

我没有在网上找到任何实现,所以我自己写了它,基于 biziclop 的想法:

/**
 * Replace the tabulator characters of a String by the corresponding number of spaces.
 * Example:<pre>
 *   1.&lt;tab&gt;firstpoint&lt;tab&gt;page  1
 *   10.&lt;tab&gt;secondpoint&lt;tab&gt;page 10 </pre>
 * will become<pre>
 *   1.      firstpoint      page  1
 *   10.     secondpoint     page 10</pre>
 *
 * @param text     the text
 * @param tabstop  the espacement between the tab stops, typically 4 or 8
 * @return The text, with no &lt;tab&gt; character anymore
 */
public static String retab(final String text, final int tabstop)
{
    final char[] input = text.toCharArray();
    final StringBuilder sb = new StringBuilder();

    int linepos = 0;
    for (int i = 0; i<input.length; i++)
    {
        // treat the character
        final char ch = input[i];
        if (ch == '\t')
        {
            // expand the tab
            do
            {
                sb.append(' ');
                linepos++;
            } while (linepos % tabstop != 0);
        }
        else
        {
            sb.append(ch);
            linepos++;
        }

        // end of line. Reset the lineposition to zero.
        if (ch == '\n' || ch == '\r' || (ch|1) == '\u2029' || ch == '\u0085')
            linepos = 0;

    }

    return sb.toString();
}
于 2012-07-30T14:48:22.217 回答
1

我使用 Java 8 Streams 重写了ANTLR Guy 的答案,还使用了 Alexis C. 的基于 Streams 的代码来重复一个字符串

static String repeatString(String s, int count) {
   return Stream.generate(() -> s).limit(count).collect(Collectors.joining());
}

static String expandTabs(String s, int tabSize) {
   int[] col = new int[1];
   return s.chars().mapToObj(c -> {
      switch (c) {
         case '\t':
            int expandBy = tabSize - col[0] % tabSize;
            col[0] += expandBy;
            return repeatString(" ", expandBy);
         case '\n':
            col[0] = 0;
            break;
         default:
            col[0]++;
      }
      return String.valueOf((char) c);
   }).collect(Collectors.joining());
}
于 2016-11-27T21:37:15.797 回答
1

Eldar(Abusalimov,Terence Parr)帖子的变体。

更改:
1. 将 if 语句拆分为两行,以便您可以在主体上设置断点
2. 使用 StringBuffer 的容量构造函数来帮助它预先分配存储空间。

public static String expandTabs(String str, int tabSize) {
    if (str == null)
        return null;
    StringBuilder buf = new StringBuilder(str.length()+tabSize);
    int col = 0;
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        switch (c) {
            case '\n' :
                col = 0;
                buf.append(c);
                break;
            case '\t' :
                buf.append(spaces(tabSize - col % tabSize));
                col += tabSize - col % tabSize;
                break;
            default :
                col++;
                buf.append(c);
                break;
        }
    }
    return buf.toString();
}

public static StringBuilder spaces(int n) {
    StringBuilder buf = new StringBuilder(n);
    for (int sp = 0; sp < n; sp++)
        buf.append(" ");
    return buf;
}
于 2018-08-12T20:46:41.783 回答