2012-08-07 3 views
3

Я работаю со свободным маркером и java. Я должен выводить результат в txt-файл. Скажем, я должен печатать для 3 столбцов какПеремещение курсора с freemarker

`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) 

ответ

0

Я не знаю FreeMarker, вот один подход только с помощью манипулирования строк:

  1. Возьми StringBuilder
  2. Хотя A, B или C имеет какие-либо символы остались
  3. Для А, добавьте экстракт не более 3 символов
  4. добавить пробелы до 8 символов
  5. Для B, добавьте экстракт не более 3 символов
  6. добавить пробелы до 8 символов
  7. Для C, добавьте экстракт не более 3 символов
  8. добавить пробелы до 8 символов
  9. Append новой строки

Вот пример кода, может не быть оптимизирован, но работает:

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?   
1

Я принял взглянуть на FreeMarker built-ins for strings, и я не думаю, что есть функция для решения этой проблемы непосредственно, но то, что вы могли бы сделать это следующим образом:

Я полагаю, у вас есть 3 списка с атрибутами в Java, которые вы передаете в свой шаблон. В шаблоне вы создаете еще 3 списка, которые будут использоваться в качестве списков буферов, сохраняющих оставшиеся символы.

С помощью функции string functionsubstring(0, 3) вы вычисляете, какая часть строки атрибута может выводиться непосредственно для столбца A, если символы остаются, вы добавляете их в первый список буферов.

Затем вы повторяете ту же процедуру для столбцов B и C. После этого столбцы A снова поворачиваются (на этот раз для второй строки). На этот раз вы не заглядываете в списки, переданные Java, а в списки буферов: есть ли еще оставшиеся символы предыдущего атрибута или можно использовать переданный список?

Если есть оставшиеся символы, то снова примените substring(0, 3) и нажмите остальные оставшиеся символы в начале списка первого буфера. И так далее и так далее ...

Я знаю, что это утомительно, но единственное решение, о котором я могу думать.

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 как TemplateDirectiveModel (или как TemplateMethodModelEx), а затем myutils.ftl изменяется на <#assign printColumns = "com.whatever.PrintColumnsDirective"?new()>.

+0

как я пишу 'while (a <4 && b <5) {; } 'в freemarker. Возможно, вы можете предложить мне ссылку, где я могу прочитать об этом. Спасибо. –

+0

Это должен был быть отдельный вопрос о стеке снова ... Что бы ни случилось. Единственным способом цикла является '# list' (и рекурсия). Следовательно, вы просто получаете достаточно большой диапазон, как я сделал выше, а затем добавляем '<#if! (A <4 && b < 5)><#break>' как первое, что в нем. – ddekany

Смежные вопросы