筛选(搜索和替换)输入流中的字节数组

2022-09-01 20:22:59

我有一个输入流,它将html文件作为输入参数。我必须从输入流中获取字节。

我有一个字符串:.我想将此字符串转换为字节格式,并检查从 InputStream 获得的字节序列中的字符串是否匹配。如果有,我必须用其他字符串的bye序列替换匹配项。"XYZ"

有没有人可以帮助我?我使用正则表达式来查找和替换。但是查找和替换字节流,我不知道。

以前,我使用jsoup来解析html并替换字符串,但是由于一些utf编码问题,当我这样做时,文件似乎已损坏。

TL;DR: 我的问题是:

在Java的原始输入流中查找和替换字节格式的字符串是一种方法吗?


答案 1

不确定您是否选择了解决问题的最佳方法。

也就是说,我不喜欢(并且作为政策不)用“不要”来回答问题,所以这里去了......

看看 FilterInputStream

从文档中:

FilterInputStream 包含一些其他输入流,它使用这些输入流作为其基本数据源,可能会在此过程中转换数据或提供其他功能。


写下来是一个有趣的练习。下面是一个完整的示例:

import java.io.*;
import java.util.*;

class ReplacingInputStream extends FilterInputStream {

    LinkedList<Integer> inQueue = new LinkedList<Integer>();
    LinkedList<Integer> outQueue = new LinkedList<Integer>();
    final byte[] search, replacement;

    protected ReplacingInputStream(InputStream in,
                                   byte[] search,
                                   byte[] replacement) {
        super(in);
        this.search = search;
        this.replacement = replacement;
    }

    private boolean isMatchFound() {
        Iterator<Integer> inIter = inQueue.iterator();
        for (int i = 0; i < search.length; i++)
            if (!inIter.hasNext() || search[i] != inIter.next())
                return false;
        return true;
    }

    private void readAhead() throws IOException {
        // Work up some look-ahead.
        while (inQueue.size() < search.length) {
            int next = super.read();
            inQueue.offer(next);
            if (next == -1)
                break;
        }
    }

    @Override
    public int read() throws IOException {    
        // Next byte already determined.
        if (outQueue.isEmpty()) {
            readAhead();

            if (isMatchFound()) {
                for (int i = 0; i < search.length; i++)
                    inQueue.remove();

                for (byte b : replacement)
                    outQueue.offer((int) b);
            } else
                outQueue.add(inQueue.remove());
        }

        return outQueue.remove();
    }

    // TODO: Override the other read methods.
}

用法示例

class Test {
    public static void main(String[] args) throws Exception {

        byte[] bytes = "hello xyz world.".getBytes("UTF-8");

        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

        byte[] search = "xyz".getBytes("UTF-8");
        byte[] replacement = "abc".getBytes("UTF-8");

        InputStream ris = new ReplacingInputStream(bis, search, replacement);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        int b;
        while (-1 != (b = ris.read()))
            bos.write(b);

        System.out.println(new String(bos.toByteArray()));

    }
}

给定它打印的字符串的字节:"Hello xyz world"

Hello abc world

答案 2

以下方法将起作用,但我不知道对性能的影响有多大。

  1. 用 ,InputStreamInputStreamReader
  2. 用替换字符串的 a 包装,然后InputStreamReaderFilterReader
  3. 用 .FilterReaderReaderInputStream

选择适当的编码至关重要,否则流的内容将损坏。

如果你想使用正则表达式来替换字符串,那么你可以使用Streamflyer,这是我的工具,这是一个方便的替代方法。您将在 Streamflyer 的网页上找到字节流的示例。希望这有帮助。FilterReader


推荐