2010-12-11 3 views
1

Я работаю с iTextSharp, и мне нужно создать сотни тысяч документов RTF - результирующие файлы находятся между 5 КБ и 500 КБ.Есть ли способ сделать это быстрее? MemoryStream vs FileStream

Я перечисляю 2 подхода ниже - первоначальный подход не обязательно был медленным, но я решил, зачем писать и извлекать из/в файл, чтобы получить нужную строку. Я видел этот другой подход, используя MemoryStream, но это фактически замедлило работу. Мне по существу просто нужен вывод RTF-контента, поэтому я могу запустить некоторые фильтры в этом RTF, чтобы очистить ненужное форматирование. Запросы, возвращающие данные, очень быстро выглядят. Для создания 1000 файлов (фактически 2000 файлов создаются в процессе) с исходными файлами подходов занимает около 15 минут, то же самое со вторым подходом занимает около 25-30 минут. Результирующие файлы, которые я запускал, составляют в среднем около 80 КБ.

Есть ли что-то не так со вторым подходом? Похоже, он должен быть быстрее первого, а не медленнее.

Оригинальный подход:

RtfWriter2.GetInstance(doc, new FileStream(RTFFilePathName, FileMode.Create)); 
doc.Open(); 

    //Add Tables and stuff here 

doc.Close(); //It saves a file here to (RTFPathFileName) 

StreamReader srRTF = new StreamReader(RTFFilePathName); 
string rtfText = srRTF.ReadToEnd(); 
srRTF.Close(); 

    //Do additional things with rtfText before writing to my final file 

Новый подход, пытаясь ускорить его, но это на самом деле в два раза быстрее:

MemoryStream stream = new MemoryStream(); 
    RtfWriter2.GetInstance(doc, stream); 
    doc.Open(); 

    //Add Tables and stuff here 

    doc.Close(); 

    string rtfText = 
    ASCIIEncoding.ASCII.GetString(stream.GetBuffer()); 
    stream.Close(); 


     //Do additional things with rtfText before writing to my final file 

Второй подход, который я пытаюсь я нашел здесь: iTextSharp - How to generate a RTF document in the ClipBoard instead of a file

+0

Каков объем файла, в котором вы работаете? Если он не очень большой, то нет, это не будет иметь большого значения. Если он большой, вы можете не захотеть обработать его в памяти, если он слишком сильно ухудшает вашу систему. – phillip

+0

Привет благодарю вас за ответ. У меня около 400 000 файлов, которые мне нужны для вывода - от 5 КБ до 500 КБ. Я использую iTextSharp для создания RTF-контента из SQL-запроса. – user53885

+0

Повторное использование Memorystream. то есть выделить его один раз и использовать его для всех файлов, очищающих его содержимое между ними. – CodesInChaos

ответ

3

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

Чтобы проверить, не является ли проблема, установленная inital размером MemoryStream, получить некоторое большое значение вокруг результирующего размера и повторно запустить код.

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

0

Как сказал Алексей, его, вероятно, вызванный фактом, каждый раз создает MemoryStream каждый раз, и каждый раз он постоянно перераспределяет память по мере ее роста. Попробуйте создать только 1 поток и перезагрузите его до начала записи перед каждой записью.

Также я думаю, что stream.GetBuffer() снова возвращает новую память, поэтому попробуйте использовать тот же StreamReader с вашим MemoryStream.

И, похоже, ваш код может быть легко парализован, поэтому вы можете попробовать запустить его с помощью Paralel Extesions или с помощью TreadPool.

И кажется немного странным, вы пишете текст в виде байтов в потоке, затем читаете этот поток в виде байтов и конвертируете в текст. Не удалось ли сохранить ваш документ непосредственно в виде текста?

0

MemoryStream не связан с файлом и не имеет понятия имени файла. В принципе, вы не можете этого сделать.

Вы, безусловно, не можете бросить между ними; вы можете только бросать вверх вниз - не вбок; визуализировать:

Stream 
     | 

| | FileStream MemoryStream Вы можете передавать поток MemoryStream потоку тривиально и поток в MemoryStream с помощью проверки типа; но никогда не FileStream для MemoryStream. Это похоже на то, что собака - это животное, а слон - животное, поэтому мы можем бросить собаку слону.

Вы можете подклассифицировать MemoryStream и добавить свойство Name (которое вы предоставляете значение), но между FileStream и YourCustomMemoryStream по-прежнему не будет общности, а FileStream не реализует уже существующий интерфейс, чтобы получить Имя; поэтому вызывающий должен будет явно обрабатывать как отдельно, так и использовать утиную печать (возможно, через динамику или отражение).

Другим вариантом (возможно, проще) может быть: запись ваших данных во временный файл; используйте FileStream; затем (позже) удалите файл.

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