【问题标题】:Remove junk trailing xml from an inputstream从输入流中删除垃圾尾随 xml
【发布时间】:2011-07-23 21:35:26
【问题描述】:

我的免费虚拟主机将分析 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 -> 传递 解决方案是否像我认为的那样可怕。

【问题讨论】:

  • 询问您的网络主机(即他们何时不发送 js)
  • 这是一个免费的虚拟主机,除非您注册他们的成熟主机,否则他们不会真正提供客户服务。 :)
  • 发送托管的图片/css时,js是否也一起发送?
  • 不,仅适用于 HTML 和 PHP 页面,但只有 *.php 文档可以包含动态内容,因此我将这些 php 文件的内容类型标头覆盖为 text/xml。

标签: java android xml xml-parsing


【解决方案1】:

我即将创建一个接收我的 InputStream 的类,请阅读 通过它直到我找到垃圾,打破,然后拿走我刚刚写的东西 to,将其转换回 InputStream 并像什么都没有一样传递它 发生了。但我担心它会非常低效,有错误 我不应该处理(例如打破二进制值,例如 嵌入图像),希望没有必要。

您可以使用 FilterStream 来实现不需要缓冲区

最好的办法是在 XML 的末尾添加一个分隔符,例如 --theXML ends HERE -- 或在 XML 中找不到的字符,例如一组 16 个 \u04 chars(然后您只需要检查每 16 个字节)到末尾的 XML 并阅读直到找到它

实现假设\u04delim

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】:

    “我将创建一个类,它将接收我的 InputStream,通读它直到我找到垃圾,中断,然后接收我刚刚写入的内容,将其转换回 InputStream 并像什么都没发生一样传递它. 但我担心它会非常低效,有我不应该处理的错误(例如破坏嵌入图像等二进制值)并且希望没有必要。”

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

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

    缺点是您将整个 XML 文件读入内存,对于大文件,内存效率可能很低。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2014-09-12
        • 2023-03-20
        • 1970-01-01
        • 2022-01-05
        相关资源
        最近更新 更多