Чтение всего содержимого Java BufferedReader, включая символы завершения строки

Я пишу TCP-клиент, который получает двоичные данные и отправляет их на устройство. Проблема возникает, когда я использую BufferedReader, чтобы прочитать то, что он получил.

Я чрезвычайно озадачен, обнаружив, что нет никакого метода, доступного для чтения всех данных. readLine() метод, который используют все, обнаруживает оба \n а также \r символы как символы окончания строки, поэтому я не могу получить данные и конкатить строки, потому что я не знаю, какой символ был символом конца строки. Я тоже не могу использовать read(buf, offset, num)потому что он не возвращает количество прочитанных байтов. Если я читаю это побайтно, используя read() метод, это стало бы ужасно медленно. Пожалуйста, кто-нибудь, скажите мне, каково решение, этот API кажется мне довольно глупым!


Ну, во-первых, спасибо всем. Я думаю, что основная проблема была в том, что я прочитал tutorialspoint вместо документации по Java. Но простите меня за это, так как я живу в Иране, а Oracle не дает нам доступа к документации по какой бы то ни было причине. В любом случае, спасибо за терпение и полезные ответы.

4 ответа

Решение

Это более чем вероятно проблема XY.

Начало вашего вопроса гласит:

Я пишу TCP-клиент, который получает двоичные данные и отправляет их на устройство. Проблема возникает, когда я использую BufferedReader, чтобы прочитать то, что он получил.

Это двоичные данные; не используйте Reader начать с! Reader оборачивает InputStream, используя Charset, и выдает поток char с не byte s. Смотрите, среди других источников, здесь для более подробной информации.

Следующий:

Я очень озадачен, обнаружив, что нет никакого метода, доступного для чтения всех данных

С разумом. Невозможно сказать, насколько большими могут быть данные, и в результате такой метод будет чреват проблемами, если получаемые вами данные слишком велики.

Итак, теперь, используя Reader что вы действительно должны сделать, это:

  • читать некоторые двоичные данные из Socket;
  • скопируйте эти данные в другой источник.

Решений для этого много; Вот одно решение, которое не требует ничего, кроме стандартного JDK (7+):

final byte[] buf = new byte[8192]; // or other

try (
    final InputStream in = theSocket.getInputStream();
    final OutputStream out = whatever();
) {
    int nrBytes;
    while ((nrBytes = in.read(buf)) != -1)
        out.write(buf, 0, nrBytes);
}

Оберните этот код в метод или что-то и т. Д.

Я чрезвычайно озадачен, обнаружив, что нет никакого метода, доступного для чтения всех данных.

Есть три.

Метод readLine(), который используют все, обнаруживает символы \n и \r как символы окончания строки, поэтому я не могу получить данные и выполнить конкатенацию строк, потому что я не знаю, какой символ был символом конца строки.

Правильный. Документально подтверждено подавление ограничителя строки.

Я также не могу использовать read(buf, offset, num), потому что он не возвращает количество прочитанных байтов.

Возвращает количество прочитанных символов.

Если бы я читал его побайтово, используя метод read(), он стал бы ужасно медленным.

Это означает, что символ за символом, а не побайтно, но вы ошибаетесь в производительности. Это буферизовано.

Пожалуйста, кто-нибудь, скажите мне, каково решение

Вы не должны использовать Reader для двоичных данных в первую очередь. Я могу только предложить вам перечитать Javadoc для:

BufferedInputStream.read() throws IOException;
BufferedInputStream.read(byte[]) throws IOException;
BufferedInputStream.read(byte[], int, int) throws IOException;

Последние два возвращают количество прочитанных байтов или -1 в конце потока.

этот API кажется мне довольно глупым!

Без комментариев.

Во-первых, каждый, кто читает данные, должен планировать \ n, \ r, \ r \ n в качестве возможных последовательностей, за исключением случаев синтаксического анализа заголовков HTTP, которые должны быть разделены \r\n. Вы можете легко читать построчно и выводить любой разделитель строк, который вам нравится.

Во-вторых, метод read возвращает количество символов, которые он прочитал в char[], так что он работает абсолютно правильно, если вы хотите прочитать блок символов и выполнить свой собственный анализ строки и вывод.

Лучшее, что я могу порекомендовать, - это использовать BufferedReader.read() и выполнять итерацию по каждому символу в файле. Что-то вроде этого:

String filename = ...
br = new BufferedReader( new FileInputStream(filename));
while (true) {
   String l = "";
   Char c = " ";
   while (true){
        c = br.read();
        if not c == "\n"{
        // do stuff, not sure what you want with the endl encoding
        // break to return endl-free line
    }
    if not c == "\r"{
        // do stuff, not sure what you want with the endl encoding
        // break to return endl-free line
        Char ctwo = ' '
        ctwo = br.read();
        if ctwo == "\n"{
            // do extra stuff since you know that you've got a \r\n
        }
    }
    else{
        l = l + c;
    }
   if (l == null) break;
    ...
   l = "";
}

ранее ответил @ arrdem

Другие вопросы по тегам