问题
I am working with free marker and java. I have to output result on a txt file. Say i have to print for 3 columns as
`A B C`
In the similar patter. All three attributes as string. Condition is that, if the length of string referring to A is more than 3 than it should be printed in the next line. That is if the length is 8 then first 3 character will be in first line, 4 to 6 in second and the remaining two in third. Now after that when I have to print for B, i would have to come back to the first line, but the current position for A will be line 3.
How do i do this?
Example
Hi, (required cursor position to print for B).
Hel
lo(current cursor position)
回答1:
I don't know freemarker, Here is one approach by just using String manipulation:
- Take a
StringBuilder
- While A, B or C has any characters left
- For A, append extract max 3 characters
- append blank spaces till 8 characters
- For B, append extract max 3 characters
- append blank spaces till 8 characters
- For C, append extract max 3 characters
- append blank spaces till 8 characters
- append newline
Here is code example, might not be optimized but works:
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();
}
Output:
Hel How Was
lo ar sup
e y
ou?
回答2:
I have taken a look at the FreeMarker built-ins for strings and I don't think there is a function to solve this directly, but what you could do is the following:
I assume you have 3 lists with the attributes in Java which you pass to your template. In the template you create another 3 lists which will be used as buffer lists storing remaining characters.
With the function string function substring(0, 3)
you compute how much of the attribute string can be outputed directly for column A, if characters remain you add them to the first buffer list.
Then you repeat the same procedure for column B and C. After that it's columns A turn again (this time for the second line). This time you don't look into the from Java passed lists, but into the buffer lists: are there still remaining characters of a previous attribute or can the passed list be used?
If there are remaining characters then apply substring(0, 3)
again and push possible remaining characters again at the front of the first buffer list. And so on and so on...
I know this is tedious, but the only solution I can think of.
回答3:
It's kind of awkward to implement purely in FreeMarker, but it's complete language enough to do it. Let's say this is in 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>
And then you can do:
<#import "myutils.ftl" as u>
...
<@u.printColumns ['Helo', "How are you?", "Wassup"] />
If you want higher performance, you may consider implementing this in Java as a TemplateDirectiveModel
(or as a TemplateMethodModelEx
), and then myutils.ftl
changes to <#assign printColumns = "com.whatever.PrintColumnsDirective"?new()>
.
来源:https://stackoverflow.com/questions/11851157/repositioning-the-cursor-with-freemarker