Экранирование большого количества символов для отображения на веб-странице XHTML через Java - PullRequest
0 голосов
/ 20 октября 2010

У меня есть встроенное устройство, которое запускает Java-приложения, которые могут, помимо прочего, обслуживать веб-страницы XHTML (я мог бы написать страницы как что-то отличное от XHTML, но сейчас я стремлюсь к этому).

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

На одной из моих страниц я хотел бынапример, для отображения (журнала) файла, размер которого может достигать 1 МБ.

Я могу отобразить этот файл без экранирования, используя следующий код:

<code>final PrintWriter writer; // Is initialized to a PrintWriter writing to the output stream.
final FileInputStream fis = new FileInputStream(file);
final InputStreamReader inputStreamReader = new InputStreamReader(fis);
try {
    writer.println("<div id=\"log\" style=\"white-space: pre-wrap; word-wrap: break-word\">");
    writer.println("    <pre>");
    int length;
    char[] buffer = new char[1024];
    while ((length = inputStreamReader.read(buffer)) != -1) {
        writer.write(buffer, 0, length);
    }
    writer.println("
"); writer.println (" ");} finally {if (inputStreamReader! = Null) {inputStreamReader.close ();}}

Это работает достаточно хорошо и отображает весь файл в течение одной или двух секунд (приемлемый период).

Этот файл может (и на практике содержит) символы, которые являются недопустимыми XHTML, чаще всего <>. Поэтому мне нужно найти способ экранирования этих символов.

Первое, что я попробовал, был раздел CDATA, но, как задокументировано здесь , они не отображаются правильно в IE8.

Вторым, что я попробовал, был метод, подобный следующему:

// Based on code: /386117/luchshii-sposob-kodirovat-tekstovye-dannye-dlya-xml-v-java#386145
// Modified to write directly to the stream to avoid creating extra objects.
private static void writeXmlEscaped(PrintWriter writer, char[] buffer, int offset, int length) {
    for (int i = offset; i < length; i++) {
        char ch = buffer[i];

        boolean controlCharacter = ch < 32;
        boolean unicodeButNotAscii = ch > 126;
        boolean characterWithSpecialMeaningInXML = ch == '<' || ch == '&' || ch == '>';

        if (characterWithSpecialMeaningInXML || unicodeButNotAscii || controlCharacter) {
            writer.write("&#" + (int) ch + ";");
        } else {
            writer.write(ch);
        }
    }
}

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

IЯ пытался использовать BufferedWriter перед PrintWriter, а также изменять размер буфера (как для чтения файла, так и для BufferedWriter) различными способами, без улучшения.

IsЕсть ли способ избежать всех недопустимых символов XHTML, который не требует повторения для каждого символа в потоке?В случае неудачи, есть ли способ ускорить мой код, достаточный для отображения этих файлов в течение пары секунд?

Я рассмотрю вопрос об уменьшении размера файлов журнала, если придется, но я надеялся сделать ихразмером не менее 250-500 КБ (при этом идеальным является 1 МБ).

У меня уже есть метод для простой загрузки файлов журнала, но я хотел бы отобразить их в браузере, а также для простого устранения неполадок / прочтения.

Если есть способ установить заголовки так, чтобы IE8 / Firefox просто отображал файл в браузере как текстовый файл, я бы посчитал это альтернативой (и имел бы целую страницу, посвященную файлу безXHTML любого типа).


РЕДАКТИРОВАТЬ:

После внесения изменения , предложенного Кэмероном Скиннером, и тестирования производительности это выглядит так, как будто на запись с выходом уходит около 1,5-В 2 раза длиннее, чем блочная версия.Это не что иное, но я, вероятно, не смогу добиться огромного ускорения, возиться с ним.

Возможно, мне просто нужно уменьшить максимальный размер файла журнала.

Ответы [ 3 ]

1 голос
/ 20 октября 2010

Один из вариантов - предоставить вам содержимое журнала внутри iframe, размещенного внутри вашей веб-страницы.Источник iframe может указывать на URL, который отображает содержимое в виде текста.

1 голос
/ 20 октября 2010

Одно небольшое изменение, которое (ну, может) может значительно увеличить скорость, - это изменение

writer.write("&#" + (int) ch + ";");

до

writer.write("&#");
writer.write((int)ch);
writer.write(";");

Конкатенация строк чрезвычайно дорога, поскольку Java выделяет новый временный строковый буфер для каждого оператора +, поэтому вы генерируете два временных буфера каждый раз, когда требуется заменить символ.

РЕДАКТИРОВАТЬ: Один из комментариев к другому ответу очень актуален: найдите, где медленный бит является первым. Я бы посоветовал протестировать журналы, в которых нет экранированных символов и экранированных символов.

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

1 голос
/ 20 октября 2010

Вы можете попробовать StringEscapeUtils от commons-lang:

StringEscapeUtils.escapeHtml(writer, string);
...