2015-09-18 4 views
0

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

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


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

+0

Я закончил тем, что написал свою собственную ленту Reader/Writer. – Kenney

+2

Но чтение (buf, offset, num) возвращает количество символов, прочитанных: http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html # read (char [],% 20int,% 20int) После того, как вы прочитаете строку, вы можете создать String из этого и затем объединить, как хотите. –

+0

Это то, что я читал в tutorialspoint: –

ответ

2

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

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

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

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

Следующая:

Я очень озадачен, узнав, что не существует метода, чтобы прочитать все данные

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

Итак, теперь, используя 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); 
} 

Wrap этот код в методе или любой другой и т.д.

-1

Лучшее, что я могу посоветовать, это использовать 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 = ""; 
} 

ранее ответил @https://stackoverflow.com/users/615234/arrdem

+0

Разве это не так медленно? –

+0

Нет, потому что BufferedReader буферизует за кулисами. – bknights

+0

Не компилируется; использует '==' для сравнения строк; сравнивает символы с строками; и не затрагивает несколько основополагающих заблуждений в вопросе. – EJP

1

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

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

2

Я очень озадачен, узнав, что есть нет метода для чтения всех данных.

Есть три.

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

Исправить. Документировано подавление терминатора линии.

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

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

Если я прочитал его byte by byte с помощью метода read(), это станет ужасно медленным.

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

Пожалуйста, кто-то сказать мне, что это решение

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

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

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

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

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

+0

Любите «Без комментариев». Сделал мой день. Благодарю. – Andreas

Смежные вопросы