Как вы можете заставить флеш на объект OutputStream, не закрывая его?

Мой вопрос кроется в следующих предположениях, которые, я надеюсь, верны, потому что я верю в это, когда читаю их, в то время как у меня проблемы с Google:

  1. Закрытие выходного потока Socket также закрывает сокет
  2. Метод flush () для OutputStream ничего не делает

Поэтому мне в основном нужно как-то вымыть данные из моего объекта OutputStream, чтобы мое приложение работало.

Если вас интересуют подробности, перейдите по следующим ссылкам:

, Странное поведение: отправка изображения с телефона Android на сервер Java (работа с кодом)

Эта проблема была решена путем закрытия OutputStream. Это привело к потере всех данных на другой конец сокета и заставила мое приложение работать дальше, но это исправление вскоре вызвало проблему номер 2 – соответствующий сокет также закрывается:

, SocketException – «Socket закрывается», даже если isConnected () возвращает true

Вы можете вызвать метод flush для OutputStream, а не закрыть. Конкретные классы, наследующие от OutputStream, переопределяют flush (), чтобы делать что-то другое, кроме ничего (запись данных в файл или отправка по сети).

Метод flush () для OutputStream ничего не делает.

Это неверно.

Верно, что базовая реализация flush() предоставляемая классом OutputStream , ничего не делает. Тем не менее, ваше приложение будет вызывать версию этого метода, предоставляемую фактическим классом потока, который вы используете. Если класс потока не имеет прямой семантики записи, он будет переопределять flush() чтобы выполнить то, что требуется.

Короче говоря, если требуется флеш (и требуется для выходного потока Socket), то вызов flush() будет правильным. (Если какой-либо интернет-источник сообщает вам, что иначе это либо неправильно, либо вы неверно истолковываете его.)


FYI, причина, по которой базовый OutputStream реализует flush() как no-op, OutputStream :

  • Некоторым классам выходного потока не нужно ничего делать, когда они промываются; Например ByteArrayOutputStream , и
  • Для классов потоков, где flush() не является no-op, не существует способа реализовать операцию на уровне базового класса.

Они могли (теоретически) OutputStream конструированные потоковые API, так что OutputStream был абстрактным классом (и абстрактным методом flush() ) или интерфейсом. Однако этот API был фактически заморожен до Java 1.0, и в то время не было достаточного опыта практического программирования на Java, чтобы понять, что дизайн API был субоптимальным.

Закрытие выходного потока Socket также закрывает сокет

Правда.

Метод flush () для OutputStream ничего не делает

Ложь. Есть переопределения. См. Javadoc для FilterOutputStream.flush() , BufferedOutputStream.flush() , ObjectOutputStream.flush() , чтобы назвать несколько.

Таким образом, ваша первоначальная проблема не существует, поэтому вам не нужно «решение», которое вызывает проблему №2.

Вам действительно нужно флеш? У меня также была проблема, когда слушатель на сервере c # не мог получать данные, отправленные с android (я пытался получить данные синхронно).

Я был уверен, что это связано с тем, что на стороне Android следующий код не сбрасывался.

 OutputStream str = btSocket.getOutputStream(); str.write(data_byte); // "This implementation does nothing" str.flush(); 

Оказалось, что если я использую асинхронный поиск данных на слушателе сервера – он получает данные, и на стороне клиента не требуется flush ()!

Я ударю на него. У меня была такая же проблема. Закрытие выходного потока – единственный способ, которым я могу «сбросить» данные. Но поскольку мне все еще нужен выходной поток, это не вариант. Поэтому 1-й я посылаю длину байтового массива, out.writeInt, затем сам массив. Когда все байты прочитаны, т.е. buffer.length == in.readInt () i break loop

  ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; byte[] fileBytes; int n; int length; try { size = in.readInt(); while((n = in.read(buffer)) != -1) { dataBuffer.write(buffer, 0, n); if(dataBuffer.toByteArray().length == length) { fileBytes = dataBuffer.toByteArray(); break; } } } 

У меня такая же проблема. Добавьте «\ n» в конец потока. Flush работает, но destinary не знает, закончилось ли сообщение

ДА на Android-флеш () ничего не делать (пример основан на api 23)

 public Socket() { this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(); this.proxy = null; } public class PlainSocketImpl extends SocketImpl { @Override protected synchronized OutputStream getOutputStream() throws IOException { checkNotClosed(); return new PlainSocketOutputStream(this); } } private static class PlainSocketOutputStream extends OutputStream { // doesn't override base class flush(); } 

Для сброса выходного потока без закрытия сокета вы можете отключить вывод:

 protected void shutdownOutput() throws IOException 

– это закроет дескриптор файла WRITE.

Вместо использования выходного потока вы можете напрямую написать файловый дескриптор или создать собственную реализацию Socket с помощью OutputStream, которая переопределит метод flush (например, с использованием реализации сокета Berkeley в c (через собственный вызов).