处理输入流

7
我该如何“修改”InputStream?我有一个文件作为输入,想要修改一些变量并转发新的InputStream。
例如,初始的InputStream包含Hello ${var}。然后我想使用var =“world”修改这个InputStream,得到InputStream Hello world。
最佳实践是什么?谢谢。
3个回答

12

java.io 是一个装饰器模式作用于所有流上的。利用它并创建一个继承自InputStream的类(也许是DataInputStream或更好的,一些Reader因为你实际上是对字符感兴趣,而不是字节,但是这样做),添加一个构造函数,该构造函数需要原始的InputStream并覆盖read()方法以读取原始流,缓冲到一定程度(例如从${一直到第一个下一个}),然后确定键并返回修改后的数据。

如果您将新类命名为FormattedInputStream,则可以将new FormattedInputStream(originalInputStream)返回给最终用户,并且最终用户仍然只需将其分配并使用它作为InputStream


嗨@BalusC,您的答案是否也适用于Excel文件?我想编辑输入流并将其发送给用户。这是我的帖子:http://stackoverflow.com/questions/34893954/grails-edit-form-multipart-file-from-client-and-send-it-back-to-the-clien?noredirect=1#comment57594193_34893954 谢谢。 - user3714598

4
您可以尝试子类化FilterInputStream
根据文档:
FilterInputStream包含另一个输入流,它将其作为基本数据源,可能会在其间转换数据或提供其他功能。FilterInputStream类本身只是使用所有请求传递到所包含的输入流版本覆盖InputStream的所有方法。FilterInputStream的子类可以进一步重写其中一些方法,并且还可以提供其他方法和字段。
以下是初步尝试。 这不是解决它的最佳方式。 您可能需要重写更多方法,甚至使用读取器。 (或者甚至使用Scanner并逐行处理文件。)
import java.io.*;
import java.util.*;

public class Test {
    public static void main(String args[]) throws IOException {
        String str = "Hello world, this is the value one ${bar} and this " +
                     "is the value two ${foo}";

        // The "original" input stream could just as well be a FileInputStream.
        InputStream someInputStream = new StringBufferInputStream(str);

        InputStream modified = new SubstitutionStream(someInputStream);
        int c;
        while ((c = modified.read()) != -1)
            System.out.print((char) c);

        modified.close();
    }
}


class SubstitutionStream extends FilterInputStream {

    Map<String, String> valuation = new HashMap<String, String>() {{
        put("foo", "123");
        put("bar", "789");
    }};

    public SubstitutionStream(InputStream src) {
        super(src);
    }

    LinkedList<Character> buf = new LinkedList<Character>();

    public int read() throws IOException {

        if (!buf.isEmpty())
            return buf.remove();

        int c = super.read();

        if (c != '$')
            return c;

        int c2 = super.read();

        if (c2 == '{') {
            StringBuffer varId = new StringBuffer();
            while ((c2 = super.read()) != '}')
                varId.append((char) c2);

            for (char vc : valuation.get(varId.toString()).toCharArray())
                buf.add(vc);

            return buf.remove();

        } else {
            buf.add((char) c2);
            return c;
        }
    }
}

输出:

Hello world, this is the value one 789 and this is the value two 123

这正是我建议使用 DataInputStream 的原因 :) (它是它的子类)。不过,毕竟,在内部使用 Reader (InputStreamReader) 更容易。 - BalusC
啊哈,我没意识到DataInputStream是一个FilterInputStream。(虽然这很有道理。)那么DataInputStream提供了什么FilterInputStream没有的功能(在这种情况下有用)? - aioobe

2
您可以使用Streamflyer,它支持字符流中的文本替换。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接