我正在处理大文件,我需要围绕base64有效负载包装XML。我的第一个天真实现将有效负载作为java.lang.String
传递到[Velocity模板] [0],但是对于大文件,我想使用java.io.InputStream
代替。
这是我的模板:
<?xml version="1.0" encoding="UTF-8"?>
<Request>
<AdditonalParameters>
#if( $headers.additionalParameters )
#foreach( $key in $headers.additionalParameters.keySet() )
<Parameter>
<Key>${key}</Key>
<Value>${headers.additionalParameters.get($key)}</Value>
</Parameter>
#end
#end
</AdditonalParameters>
<Content>${body}</Content>
</Request>
$body
可能非常大,因此我希望避免使用String
或byte[]
。可以将InputStream
作为$body
传递到我的模板中,还是不能使用Velocity?
答案 0 :(得分:1)
是的,这可以做到。所需要的只是一个逐行打印InputString
的迭代。由于Velocity缺少类似while
的构造,并且只知道foreach
循环,因此迭代在其最简单的实现中看起来就像一个丑陋的黑客:
#foreach ($i in [0..100000])
#set ($line = false)
#set ($line = $body.readLine())
#if ($line)
${line}
#else
#break
#end
#end
这里使用一个非常大的数值范围来模拟无限循环。当无法从#break
(InputStream
)中提取更多行时,循环将$body
。警告在第三行:
#set (line = $body.readLine())
与Velocity一样,分配的左侧仅在右侧的值不为空时才会更改。由于永远不会为$line
分配空值,因此我们需要将其预先设置为false
(布尔值,而不是readLine
返回的字符串)。这样,如果$line
在第二个false
之后仍为#set
,我们就会知道readLine
返回null并且是时候退出迭代了。
此方法的问题是在行之间插入的模板中有空格。有一些技巧可以避免这种情况(see here)。此外,可以通过创建Java #foreach
来避免List
黑客攻击,iterator()
方法返回Iterator
迭代InputStream
的行。这将更少KISS,但它会使您的代码更可重用。