Удалить тянущийся xml из входного потока - PullRequest
0 голосов
/ 24 июля 2011

Мой бесплатный веб-хостинг добавляет аналитический javascript ко всем файлам PHP и HTML.Это нормально, за исключением того, что я хочу отправить XML в мое приложение для Android, и это делает мои файлы недействительными.

Поскольку XML анализируется полностью (и разрушается) перед передачей в мой SAX ContentHandler, я не могу просто перехватить исключение и продолжить весело вместе с выделенным объектом.(Который я пробовал, а потом чувствовал себя неловко.)

Есть предложения относительно разумно эффективной стратегии?

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

FWIW, это частьпроект Android, поэтому я использую класс android.util.Xml (см. исходный код ).Когда я отследил исключение, он взял меня к функции native appendChars, которая сама в любом случае вызывается из сети частных методов, поэтому подклассификация чего-либо представляется необоснованно бесполезной.

ВотОтличительный бит из моей трассировки стека:

E/AndroidRuntime(  678): Caused by: org.apache.harmony.xml.ExpatParser$ParseException: At line 3, column 0: junk after document element
E/AndroidRuntime(  678):    at org.apache.harmony.xml.ExpatParser.parseFragment(ExpatParser.java:523)
E/AndroidRuntime(  678):    at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:482)
E/AndroidRuntime(  678):    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:320)
E/AndroidRuntime(  678):    at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:277)

Я думаю, в конце концов, я спрашиваю мнения о том, InputStream -> анализировать ли вручную OutputStream -> воссоздать InputStream -> передать Решение так же ужасно, как я думаю.

Ответы [ 3 ]

0 голосов
/ 24 июля 2011

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

вы можете использовать FilterStream для этого нет необходимости в буфере

лучшее, что нужно сделать, это добавить разделитель в конец XML, например --theXML ends HERE --, или символ, не найденный в XML, например, группу из 16 \u04 символов (вам нужно только проверить каждый 16-й байт) до конца XML и читайте, пока не найдете его

реализация предполагает \u04 delim

class WebStream extends FilterInputStream {

    byte[] buff = new byte[1024];
    int offset = 0, length = 0;

    public WebStream(InputStream i) {
        super(i);
    }

    @Override
    public boolean markSupported() {
        return false;
    }

    @Override
    public int read() throws IOException {
        if (offset == length)
            readNextChunk();
        if (length == -1)
            return -1;// eof
        return buff[offset++];
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        if (offset == length)
            readNextChunk();
        if (length == -1)
            return -1;// eof

        int cop = length - offset;
        if (len < cop)
            cop = len;
        System.arraycopy(buff, offset, b, off, cop);
        offset += cop;
        return cop;
    }

    private void readNextChunk() throws IOException {
        if (offset <= length) {
            System.arraycopy(buff, offset, buff, 0, length - offset);
            length -= offset;
            offset = 0;
        }
        int read = in.read(buff, length, buff.length - length);
        if (read < 0 && length <= 0) {
            length = -1;
            offset = 0;
            return;
        }

        // note that this is assuming ascii compatible
        // anything like utf16 or utf32 will break here
        for (int i = length; i < read + length; i += 16) {
            if (buff[i] == 0x04) {
                while (buff[--i] == 0x04)
                    ;// find beginning of delim block
                length = i;
                read = 0;
            }
        }
    }

}

обратите внимание, что это пропускает броски, некоторая проверка ошибок и требует правильной отладки

0 голосов
/ 18 января 2018

Free webhost имеют эту проблему. Мне еще предстоит найти альтернативу в свободном режиме.

0 голосов
/ 24 июля 2011

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

Это сработает. Вы можете прочитать в StringBuffer, а затем использовать ByteArrayInputStream или что-то подобное (например, StreamReader, если это применимо).

http://developer.android.com/reference/java/io/ByteArrayInputStream.html

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

В качестве альтернативы, вы можете создать подкласс InputStream и выполнить фильтрацию через поток. Вам, вероятно, просто нужно переопределить 3 метода read (), вызвав super.read () и пометив, когда вы дойдете до мусора в конце, и вернуть EOF по мере необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...