2010-09-02 3 views
0

Мне нужно загрузить и обработать шаблон в freemarker. Я использую поток с потоками, чтобы считывать сгенерированный результат freemarker.Проблема с трубопроводом в Freemarker

Пример кода:

PipedInputStream pi = new PipedInputStream(); 
PipedOutputStream po = new PipedOutputStream(pi); 
Writer writer = new OutputStreamWriter(po); 
configuration.getTemplate("xx").process(rootMap, writer); 

Вопрос заключается в том, что иногда это замораживание внутри метода FreeMarker procsss. Ошибка, исключение, но она не возвращается из метода process.

Если я конвертирую поток с потоком в поток ByteArray, он отлично работает.

Правильно ли я использую поток трубопроводов?

+0

Почему вы хотите прочитать результат? Что вы хотите с этим делать? –

+0

@Arne: Я хочу прочитать сгенерированный шаблон и записать его в другой поток. (zip-поток). – mhshams

+0

Почему бы просто не использовать OutputStreamWriter в потоке zip? –

ответ

2

Нет, потоки с потоками предназначены для передачи данных между двумя потоками. Между концами трубы имеется только небольшой буфер. Если вы напишете в поток потока с каналами, ваш поток будет заблокирован, если буфер заполнен до тех пор, пока другой поток не будет считываться из соответствующего потока входных каналов. Это не будет работать только с одним потоком.

Из Javadoc:

Как правило, данные считываются из объекта PipedInputStream одним нити и данные записываются в соответствующего PipedOutputStream по какой-либо другой нити.

Так что для небольших шаблонов просто использовать StringWriter, для больших, вы можете использовать FileWriter на временный файл, созданный File.createTempFile().

+0

спасибо за повтор. У вас есть какое-либо другое решение для больших шаблонов? Я не могу написать временный файл. (Не иметь доступа) – mhshams

+0

@ mohammed: У вас действительно нет доступа? Или вы просто не знаете правильное место для записи?Обычно есть временный каталог, на который у вас есть разрешение, если вы можете выяснить, где (подсказка: посмотрите на свойство 'java.io.tmpdir'). –

+0

@Donal: приложение, запущенное на сервере (OSGI), и я не уверен, что могу писать файл в среде клиента. – mhshams

0

Как пишет Арне, количество буферного пространства в потоке с каналами довольно невелико. Если вы не можете использовать буфер, который может хранить все данные (будь то в памяти или на диске), то одна вещь, которую вы могли бы попробовать, - проверить, можно ли запустить обработку шаблона в другом потоке с потоком, переданным по каналам, отправляющим результаты обратно в основной поток, где вы это делаете.

PipedInputStream pi = new PipedInputStream(); 
final Writer writer = new OutputStreamWriter(new PipedOutputStream(pi)); 
Thread worker = new Thread(new Runnable() { 
    public void run() { 
     configuration.getTemplate("xx").process(rootMap, writer); 
    } 
}); 
worker.start(); 

Вам может понадобиться добавить final ключевые слова к другим переменным, чтобы сделать эту работу в вашем реальном коде. Это зависит от того, является ли переменная configuration аргументом getTemplate или переменной rootMap являются локальными переменными или переменными экземпляра (или класса).

(я мог бы подклассы Thread при определении поведения потока, конечно, но я предпочитаю, чтобы создать экземпляр интерфейса - Runnable в данном случае -. Для таких вещей)

0

Это, как я сделал его работу.

final String uploadReportAsCsv = FreeMarkerTemplateUtils.processTemplateIntoString(
         fileUploadReportTemplate, modelMap); 

message.addAttachment("fileUploadProcessedReport.csv", 
    new InputStreamSource() { 
     //InputStreamResource from Spring is always returning an open stream, 
     // thus we need to create this anonymous class. 
     @Override 
     public InputStream getInputStream() throws IOException { 
      return new StringInputStream(uploadReportAsCsv); 
     } 
    } 
); 
Смежные вопросы