Замена символов в Java 1.4 InputStream - PullRequest
3 голосов
/ 04 марта 2011

У меня есть InputStream, который возвращает, например:

<?xml version='1.0' ?><env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><bbs:rule xmlns:bbs="http://com.foo/bbs">

Затем я передаю поток методу, который возвращает байтовый массив.Я хотел бы заменить "com.foo" чем-то другим, например, "org.bar", прежде чем перейти к методу byte [].

Каков хороший способ сделать это?

Ответы [ 4 ]

1 голос
/ 04 марта 2011

Поток читает / записывает байты.Попытка заменить текст в двоичном представлении вызывает проблемы.Поэтому первое, что нужно сделать, - это обернуть этот поток в Reader (например, InputStreamReader), который позаботится о преобразовании двоичных данных в символьную информацию для вас.Вам нужно знать кодировку ваших потоковых данных, чтобы убедиться, что они интерпретируются правильно.Например, UTF-8 или ISO-8859-1.

Когда у вас есть текстовые данные, вы можете подумать о том, как их заменить.Один из способов сделать это - использовать регулярные выражения.Однако это означает, что вам сначала нужно прочитать весь поток в строку, выполнить подстановку, а затем вернуть байтовый массив.Для больших объемов данных это может быть неэффективно.

Поскольку вы имеете дело с данными XML, вы могли бы использовать более высокий уровень подхода и каким-то образом анализировать XML, что позволяет обрабатывать содержимоебез необходимости хранить их полностью в промежуточном формате.SAXParser с вашим собственным ContentHandler сделает свое дело.Когда наступают события, просто запишите их снова, но с соответствующими изменениями.Другим подходом было бы преобразование XSLT с некоторой магией функции расширения.

Разве не предполагалось, что в java.nio будет какая-то поддержка потоковых манипуляций, подобных этой?Или это было запланировано для следующей версии Java?

1 голос
/ 04 марта 2011

Если у вас есть байт-массив, вы можете преобразовать его в строку. Обратите внимание на кодировку, в примере я использую utf-8. Я думаю, что это простой способ сделать это:

String newString = new String(byteArray, "utf-8");
newString = newString.replace("com.foo", "org.bar");
return newString.getBytes("utf-8");
1 голос
/ 04 марта 2011

Один из способов - заключить ваш InputStream в собственный подкласс FilterInputStream, который выполняет преобразование на лету. Это должен быть упреждающий поток, который проверяет каждый символ «c», чтобы увидеть, следует ли за ним «om.foo» и, если это так, сделать подстановку. Вам, вероятно, придется переопределить только метод read().

0 голосов
/ 04 марта 2011

Возможно, это не самый эффективный способ сделать это, но он, безусловно, работает.

    InputStream is = // input;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(baos));

    String line = null;

    while((line = reader.readLine()) != null)
    {
        if(line.contains("com.foo"))
        {
            line = line.replace("com.foo", "org.bar");
        }

        writer.write(line);
    }

    return baos.toByteArray();
...