从输入流中删除垃圾尾随xml

时间:2011-07-23 21:35:26

标签: java android xml xml-parsing

我的免费虚拟主机将分析javascript附加到所有PHP和HTML文件。这很好,除了我想将XML发送到我的Android应用程序,它使我的文件无效。

由于XML在传递给我的SAX ContentHandler之前被完整地解析(并且爆炸),我不能只捕获异常并继续快速地与一个充实的对象一起继续。 (我试过,然后感到羞怯。)

对合理有效策略的任何建议?

我即将创建一个将接受我的InputStream的类,读取它直到我找到垃圾,中断,然后接受我刚才写的内容,将其转换回InputStream并传递它,就像没有发生任何事情一样。但我担心它会非常低效,有我不应该处理的错误(例如打破嵌入式图像等二进制值),希望没必要。

FWIW,这是Android项目的一部分,所以我使用的是android.util.Xml类(请参阅source code)。当我跟踪异常时,它带我去了一个 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 :(得分:0)

“我即将创建一个将接收我的InputStream的类,读取它直到我找到垃圾,中断,然后接受我刚写的内容,将其转换回InputStream并传递它,就像没有发生任何事情一样但是我担心它会非常低效,有我不应该处理的错误(例如打破嵌入式图像等二进制值),希望没必要。“

那会有用。您可以读入StringBuffer,然后使用ByteArrayInputStream或类似的东西(如果适用,则使用StreamReader)。

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

缺点是你正在将整个XML文件读入内存,对于大文件,它可能在内存方面效率低下。

或者,您可以继承InputStream并通过流进行过滤。您可能只需要通过调用super.read()来覆盖3个read()方法,并在最后获得垃圾时进行标记并根据需要返回EOF。

答案 1 :(得分:0)

  

我即将创建一个将我的InputStream读取的类   通过它,直到我找到垃圾,休息,然后采取我刚刚写的东西   to,将其转换回InputStream并将其传递给任何东西   发生了。但我担心它会非常低效,有虫子   我不应该处理(例如打破二进制值,如   嵌入式图像),希望没必要。

您可以使用FilterStream,因为不需要缓冲区

最好的办法是在XML的末尾添加分隔符,如--theXML ends HERE --,或者在XML中找不到的字符,如16 \u04 chars组(您只需要检查每个第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;
            }
        }
    }

}

注意这个未命中,一些错误检查并需要正确的调试

答案 2 :(得分:0)

免费 webhost 有此问题。我还没有找到一个仍处于免费模式的替代方案。