2016-03-14 6 views
0

Я видел, как это всегда:одной линии с помощью чтения и записи потоков Java

int count = line.read(buffer, 0, buffer.length); 
if (count > 0) { 
    out.write(buffer, 0, count); 
} 

Другой пример

byte[] buffer = new byte[1024]; // Adjust if you want 
int bytesRead; 
while ((bytesRead = input.read(buffer)) != -1) { 
    output.write(buffer, 0, bytesRead); 
} 

другой ...

int numRead; 
    while ((numRead = is.read(buf)) >= 0) { 
     os.write(buf, 0, numRead); 
    } 

Я никогда не видел что-то например:

while (true) { 
    try { 
     output.write(BytesArray, 0, input.read(BytesArray, 0, BytesArray.length)); //Single line for read and write!!!! 
    } catch (IOException e) { 
     System.out.println("I can't write!"); 
     break; 
    } catch (ArrayIndexOutOfBoundsException e) { 
     System.out.println("I can't read!"); 
     break; 
    } 
    } 

В чем проблема с использованием OuputStream Написание чего-то нового, прочитанного InputStream?

Есть ли какая-то проблема?

EDIT InputStream.read работы именно тогда, когда OutputStream.write работы, и терпит неудачу, когда другой также не; Точно так же OutputStream.write работает, когда InputStream.read так делает и останавливается, когда другой тоже не может этого сделать.

Когда InputStream.read(...) не удается (или не может читать больше), этот метод возвращает -1; но, когда OutputStream.write(...) терпит неудачу (или не может писать больше), этот метод генерирует исключение IOException.

Я лично считаю, что: когда OutputStream.write(...) не может писать, должен возвращать «-1» точно так же, как InputStream.read(...) делает, когда не может прочитать.

ВОПРОС: верю вам, что InputStream.read(...)OutputStream.write(...) и они должны быть обработаны таким же образом (как возвращается -1)?

Примечание: Я знаю, что этот метод OutputStream: public void write(...)

+1

Использование обработки исключений для выполнения потока управления - особенно когда это не нужно из-за API - это плохая практика. –

+1

«Одиночная строка для чтения и записи !!!!» Позор по всем другим дополнительным линиям. –

+0

@ AndyTurner благодарит вас Andy, когда 'InputStream.read (...)' возвращает '-1' вызывается ArrayIndexOutOfBoundsException, тогда необходимо отделить строки для чтения и записи. Но какова альтернатива 'catch (ArrayIndexOutOfBoundsException e)', используя только одну строку? –

ответ

2

Использование обработки исключений для выполнения потока управления - когда нет необходимости из-за API - это плохая практика.

Если ваша причина для этого состоит в том, чтобы вы могли писать заявления на одной строке, вы должны оценить причины, по которым вы считаете, что лучше писать инструкции на одной строке. Мой телефон имеет достаточно большой экран, чтобы одновременно отображать все четыре примера выше, и я не кодирую на своем телефоне, поэтому я не могу представить ситуацию, когда пишу что-то по одной строке, потому что я могу написать это на одной линии "- достаточно убедительная причина.

Кроме того, считают ли на самом деле делает тот факт, что вы можете написать некоторые из заявлений по одной строке кода короче в целом:

while (true) { 
    try { 
    output.write(buffer, 0, input.read(buffer, 0, buffer.length); 
    } catch (ArrayIndexOutOfBoundsException e) { 
    break; 
    } 
} 

(я не обращая внимания на IOException здесь, как вы в первых трех примерах - его нужно обрабатывать, однако вы пишете код, поэтому он не имеет значения для разницы между 4 версиями с точки зрения количества кода).

Сравните это эквивалентный код от подхода 2 (ближайший эквивалент):

int bytesRead; 
while ((bytesRead = input.read(buffer)) != -1) { 
    output.write(buffer, 0, bytesRead); 
} 

который намного более кратким.

Но, как я уже упоминал выше, краткость кода на самом деле не является мерой качества кода, поэтому сама по себе это не повод отклонить предлагаемую версию. Тем не менее, есть и более фундаментальные причины, почему это не хороший подход ...


В предлагаемом коде, есть два ожидаемые типа исключения: IOException и ArrayIndexOutOfBoundsException. Эти исключения из принципиально иной природы:

  • The IOException, как ожидается, в результате чтения или записи неудачи (который является фактическим исключительным условием, и, следовательно, является подходящим использованием исключения).

    IOException является проверено исключение. Проверяемые исключения должны обрабатываться (это ошибка времени компиляции). Они предназначены для указания восстановительных условий и условий, которые не поддаются контролю API. Например, если вы пишете на диск или в сети, вы не можете контролировать, заполняется ли диск другим процессом или если подрядчики, выкапывающие дорогу, собираются сократить ваше оптоволоконное соединение. Проверенные исключения указывают на то, что «это может быть успешным, если вы попробуете еще раз позже» (когда диск не будет полным, или подрядчики зафиксировали волокно)

  • Ожидается, что ArrayIndexOutOfBoundsException будет достигнуть конца входного потока (что не является исключительным условием, так как почти все потоки заканчиваются и, следовательно, не являются надлежащим использованием исключения и не являются необходимым использованием исключения, поскольку оно обнаруживается с помощью возвращаемых значений чтения).

    ArrayIndexOutOfBoundsException is unchecked исключение, возникающее из-за ошибки в программировании - с использованием API таким образом, который он не предназначен для использования. Неконтролируемые исключения не нужно обрабатывать (это не ошибка времени компиляции, если вы этого не сделаете), поскольку они предназначены для указания в основном неустранимых условий, таких как ошибки программирования. Например, если вы попытаетесь запустить какой-то код с определенным входом, и он выдает исключение из-за ошибки программирования, он выкинет одно и то же исключенное исключение позже, потому что он работает с тем же кодом.

Таким образом, в то время как вы можете поймать и восстановить из непроверенных исключений, то есть не то, что они были предназначены для (именно поэтому вы не имеют к). Легче написать код, чтобы исключение не происходило в первую очередь.

И это легко в этом случае: Javadoc for OutputStream говорит:

Если off отрицательные, или len отрицательные, или off+len больше, чем длина массива b, затем IndexOutOfBoundsException брошен.

Итак, соблюдайте эти условия, и вам не нужно беспокоиться об этом.

(И вы должны были ловить IndexOutOfBoundsException вместо ArrayIndexOutOfBoundsException в любом случае, потому что некоторые реализации OutputStream не может бросить последний.)

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

является неконтролируемым исключение любого типа может быть выброшено из любого места в цепочке вызовов конкретного вызова - Вы могли бы ожидать , что это происходит потому, что OutputStream.write не нравится отрицательный len параметра, но он может на самом деле вызывать все остальное в OutputStream.write - или в InputStream.read - или в любом из других методов, которые они называют транзитивно, - вы не можете точно сказать (не проверяя трассировку стека, однако детали того, что вы должны проверять трассировку стека поскольку они специфичны для реализации, и, таким образом, потребуется много усилий, чтобы сделать это достаточно прочным).

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

Итак, лучше всего написать код, чтобы он не полагался на обнаружение определенного неконтролируемого исключения. В тех случаях, когда это задокументировано, что он будет вызывать такое исключение при определенных обстоятельствах, избегать этих обстоятельств.