3

我正在使用免费的标记和 java。我必须在 txt 文件中输出结果。假设我必须打印 3 列作为

`A     B      C`

在类似的模式。所有三个属性都作为字符串。条件是,如果引用 A 的字符串长度大于 3,则应该在下一行打印。也就是说,如果长度为 8,那么前 3 个字符将在第一行,4 到 6 在第二行,其余两个在第三行。现在,当我必须为 B 打印时,我必须回到第一行,但 A 的当前位置将是第 3 行。

我该怎么做呢?

例子

Hi,                          (required cursor position to print for B).
Hel
lo(current cursor position)
4

3 回答 3

1

我查看了字符串的 FreeMarker 内置函数,我认为没有直接解决此问题的函数,但您可以执行以下操作:

我假设您有 3 个列表,其中包含您传递给模板的 Java 属性。在模板中创建另外 3 个列表,这些列表将用作存储剩余字符的缓冲区列表。

使用函数字符串函数 substring(0, 3),您可以计算可以直接为 A 列输出多少属性字符串,如果仍有字符,则将它们添加到第一个缓冲区列表中。

然后对 B 列和 C 列重复相同的过程。之后,A 列再次转动(这次是第二行)。这次您不查看 from Java 传递的列表,而是查看缓冲区列表:是否还有前一个属性的剩余字符或者可以使用传递的列表?

如果还有剩余字符,则再次应用substring(0, 3)并将可能的剩余字符再次推送到第一个缓冲区列表的前面。等等等等...

我知道这很乏味,但我能想到的唯一解决方案。

于 2012-08-07T18:02:06.847 回答
0

我不知道freemarker,这是一种仅使用字符串操作的方法:

  1. 拿一个StringBuilder
  2. 而 A、B 或 C 还剩下任何字符
  3. 对于 A,追加提取最多 3 个字符
  4. 追加空格直到 8 个字符
  5. 对于 B,追加提取最多 3 个字符
  6. 追加空格直到 8 个字符
  7. 对于 C,追加提取最多 3 个字符
  8. 追加空格直到 8 个字符
  9. 追加换行符

这是代码示例,可能未优化但有效:

public static void main(String[] args) {
  System.out.println(formatOutput("Hello", "How are you?", "Wassup"));
}

public static String formatOutput(String textA, String textB, String textC) {
    StringBuilder output = new StringBuilder("");

    int beginIndex = 0, endIndex = 3;
    String snippet;
    while (textA.length() > 0 || textB.length() > 0 || textC.length() > 0) {
        if (textA.length() > endIndex) {
            snippet = textA.substring(beginIndex, endIndex);
            textA = textA.substring(endIndex);
        } else {
            snippet = textA.substring(beginIndex);
            textA = "";
        }
        output.append(snippet);
        for (int i = snippet.length(); i <= 8; i++)
            output.append(" ");
        ;

        if (textB.length() > endIndex) {
            snippet = textB.substring(beginIndex, endIndex);
            textB = textB.substring(endIndex);
        } else {
            snippet = textB.substring(beginIndex);
            textB = "";
        }
        output.append(snippet);
        for (int i = snippet.length(); i <= 8; i++)
            output.append(" ");


        if (textC.length() > endIndex) {
            snippet = textC.substring(beginIndex, endIndex);
            textC = textC.substring(endIndex);
        } else {
            snippet = textC.substring(beginIndex);
            textC = "";
        }
        output.append(snippet);
        for (int i = snippet.length(); i <= 3; i++)
            output.append(" ");
        output.append("\n");    
    }
    return output.toString();
}

输出:

Hel      How      Was 
lo        ar      sup 
         e y          
         ou?          
于 2012-08-07T18:11:01.087 回答
0

纯粹在 FreeMarker 中实现有点尴尬,但它的完整语言足以做到这一点。假设这是在myutils.ftl

<#function safeSubstring s start end>
  <#if s?length < start><#return ''></#if>
  <#if s?length < end>
    <#return s?substring(start)>
  <#else>
    <#return s?substring(start, end)>
  </#if>
</#function>

<#macro printColumns cols>
    <#list 0..999999 as i>
      <#local start = i * 3>
      <#local printedSomething = false>
      <#list cols as col>
        <#if start < col?length>
          <#local printedSomething = true>
          <#lt><#list cols as col>${safeSubstring(col, start, start + 3)?right_pad(8)}</#list>
          <#break>
        </#if>
      </#list>
      <#if !printedSomething><#break></#if>
    </#list>
</#macro>

然后你可以这样做:

<#import "myutils.ftl" as u>
...
<@u.printColumns ['Helo', "How are you?", "Wassup"] />

如果您想要更高的性能,您可以考虑在 Java 中将其实现为 a TemplateDirectiveModel(或 a TemplateMethodModelEx),然后myutils.ftl更改为<#assign printColumns = "com.whatever.PrintColumnsDirective"?new()>.

于 2012-08-08T06:40:55.867 回答