gpt4 book ai didi

java - 格式化输入流的正确方法

转载 作者:行者123 更新时间:2023-12-04 06:38:25 24 4
gpt4 key购买 nike

我有以下问题:我的程序传递了一个我无法控制其内容的 InputStream。我使用 javax 库解码我的输入流,如果 InputStream 包含 & 字符而不后跟“amp;”,它会正确地抛出异常

我想出的解决方法是创建以下类:

import java.io.ByteArrayInputStream;
import java.io.FilterInputStream;
import java.io.InputStream;

/**
* Provide an input stream where all & characters are properly encoded as &
*/
public class FormattedStream extends FilterInputStream {
public FormattedStream(InputStream src) {
super(new ByteArrayInputStream(StringUtil.toString(src)
.replace("&", "&").replace("amp;amp;", "amp;").getBytes()));
}
}

注意:StringUtil 是一个简单的实用程序,我必须将输入流转换为字符串。

有了那个类,我现在调用 JAXB 解码器:
unmarshal(new FormattedStream(inputStream));

代替
unmarshal(inputStream);

这种方法有效,但由于以下几个原因看起来很奇怪:

1 - 由于 super 必须是构造函数中的第一个元素的限制(尽管我读过它,但我无法理解的限制),我被迫在一行中完成所有处理,使代码远非可读。

2 - 将整个流转换为字符串并返回到流似乎过大

3 - 上面的代码有点不正确,因为流包含 amp;amp;将被修改为包含 amp;

我可以通过为 FormatInputStream 类提供一种方法来解决 1:
InputStream preProcess(InputStream inputStream)

我将在其中执行我目前在 FormattedStream 类的构造函数中执行的相同操作,但由于编码限制而不得不选择不同的接口(interface)似乎很奇怪。

我可以通过保持我的 FormattedStream 构造函数简单来解决 2:
super(src)

并覆盖三个读取方法,但这将涉及更多的编码:与我目前可以利用 replaceAll String 方法的一行代码相比,通过动态替换 & 来覆盖三个读取方法并非易事。

至于 3,这似乎是一个角落案例,我不担心,但也许我应该......

关于如何以更优雅的方式解决我的问题的任何建议?

最佳答案

我同意 McDowell 的回答,即 最重要的是修复无效的数据源首先。

无论如何,这是一个InputStream寻找孤独&字符并将它们与额外的 amp; 结婚以防它丢失。同样,以这种方式修复损坏的数据在大多数情况下都不会得到返回。

这个解决方案修复了 OP 中提到的三个缺陷,并且只展示了一种实现转换 InputStreams 的方法。

  • 在构造函数中,仅保留对原始 InputStream 的引用。 构造函数中不进行任何处理 , 直到流真正被要求提供数据(通过调用 read())。
  • 内容为未转换为大的单个字符串 为转型。相反,流作为流工作并且只执行最少的预读(例如,找出 & 后面是否跟 amp; 所需的四个字节。
  • 流只代替寂寞& , 和 不尝试清理 amp;amp; 无论如何,因为这种解决方案不会发生这种情况。

  • .
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayDeque;
    import java.util.Deque;

    public class ReplacerInputStream extends InputStream {

    private static final byte[] REPLACEMENT = "amp;".getBytes();
    private final byte[] readBuf = new byte[REPLACEMENT.length];
    private final Deque<Byte> backBuf = new ArrayDeque<Byte>();
    private final InputStream in;

    public ReplacerInputStream(InputStream in) {
    this.in = in;
    }

    @Override
    public int read() throws IOException {
    if (!backBuf.isEmpty()) {
    return backBuf.pop();
    }
    int first = in.read();
    if (first == '&') {
    peekAndReplace();
    }
    return first;
    }

    private void peekAndReplace() throws IOException {
    int read = super.read(readBuf, 0, REPLACEMENT.length);
    for (int i1 = read - 1; i1 >= 0; i1--) {
    backBuf.push(readBuf[i1]);
    }
    for (int i = 0; i < REPLACEMENT.length; i++) {
    if (read != REPLACEMENT.length || readBuf[i] != REPLACEMENT[i]) {
    for (int j = REPLACEMENT.length - 1; j >= 0; j--) {
    // In reverse order
    backBuf.push(REPLACEMENT[j]);
    }
    return;
    }
    }
    }

    }

    该代码已使用以下输入数据进行了测试(第一个参数是预期输出,第二个参数是原始输入):
        test("Foo &amp; Bar", "Foo & Bar");
    test("&amp;&amp;&amp;", "&&&");
    test("&amp;&amp;&amp; ", "&&& ");
    test(" &amp;&amp;&amp;", " &&&");
    test("&amp;", "&");
    test("&amp;", "&amp;");
    test("&amp;&amp;", "&amp;&amp;");
    test("&amp;&amp;&amp;", "&amp;&&amp;");
    test("test", "test");
    test("", "");
    test("testtesttest&amp;", "testtesttest&");

    关于java - 格式化输入流的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4586222/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com