Главная страница
Навигация по странице:

  • Оболочка типа Метод преобразования Double

  • Float static float parseFloat(String str) throws NumberFormatException Long

  • Integer static int parselnt(String str) throws NumberFormatException Short

  • Пример для опробования 10.2.

  • 3) Отличие пакетов IO и NIO, InputStream от Reader.

  • “Java NIO vs. IO”

  • Потокоориентированный и буфер-ориентированный ввод/вывод

  • Блокирующий и неблокирующий ввод/вывод

  • Reader

  • Метод

  • Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока


    Скачать 1.93 Mb.
    НазваниеJava io. Ключевым понятием здесь является понятие потока
    Дата03.07.2022
    Размер1.93 Mb.
    Формат файлаdoc
    Имя файлаОтветы на вопросы по ревью 4.doc
    ТипДокументы
    #623608
    страница14 из 39
    1   ...   10   11   12   13   14   15   16   17   ...   39

    Применение оболочек типов для преобразования символьных строк в числа


    Прежде чем завершить обсуждение средств ввода-вывода, необходимо рассмотреть еще один способ, помогающий читать числовые строки. Как известно, метод println() предоставляет удобные средства для вывода на консоль различных типов данных, в том числе целых чисел и чисел с плавающей точкой. Он автоматически преобразует числовые значения в удобную для чтения форму. Но в Java отсутствует метод, который читал бы числовые строки и преобразовывал бы их во внутреннюю двоичную форму. Например, не существует варианта метода read(), который читал бы числовую строку "100" и автоматически преобразовывал ее в целое число, пригодное для хранения в переменной типа int. Но для этой цели в Java имеются другие средства. И проще всего подобное преобразование осуществляется с помощью так называемых оболочек типов.

    Оболочки типов в Java представляют собой классы, которые инкапсулируют простые типы. Оболочки типов необходимы, поскольку простые типы не являются объектами, что ограничивает их применение. Так, простой тип нельзя передать методу по ссылке. Для того чтобы исключить ненужные ограничения, в Java были предусмотрены классы, соответствующие каждому из простых типов.

    Оболочками типов являются классы Double, Float, Long, Integer, Short, Byte, Character и Boolean. Эти классы предоставляют обширный ряд методов, позволяющих полностью интегрировать простые типы в иерархию объектов Java. Кроме того, в классах-оболочках числовых типов содержатся методы, предназначенные для преобразования числовых строк в соответствующие двоичные эквиваленты. Эти методы приведены ниже. Каждый из них возвращает двоичное значение, соответствующее числовой строке.

    Оболочка типа

    Метод преобразования

    Double

    static double parseDouble(String str) throws NumberFormatException

    Float

    static float parseFloat(String str) throws NumberFormatException

    Long

    static long parseLong(String str) throws NumberFormatException

    Integer

    static int parselnt(String str) throws NumberFormatException

    Short

    static short parseShort(String str) throws NumberFormatException

    Byte

    static byte parseByte(String str) throws NumberFormatException

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

    Методы синтаксического анализа позволяют без труда преобразовать во внутренний формат числовые значения, введенные в виде символьных строк с клавиатуры или из текстового файла. Ниже приведен пример программы, демонстрирующий применение для этих целей методов parselnt() и parseDouble(). В этой программе находится среднее арифметическое ряда чисел, введенных пользователем с клавиатуры. Сначала пользователю прелагается указать количество числовых значений для обработки, а затем программа вводит числа с клавиатуры, используя метод readLine(), а с помощью метода parselnt() преобразует символьную строку в целочисленное значение. Далее осуществляется ввод числовых значений и последующее их преобразование в тип double с помощью метода parseDouble().

    /* Эта программа находит среднее арифметическое для

    ряда чисел, введенных пользователем с клавиатуры. */

    import java.io.*;
    class AvgNums {

    public static void main(String args[])

    throws IOException

    {

    // создать объект типа BufferedReader,

    // использующий поток ввода System.in

    BufferedReader br = new

    BufferedReader(new InputStreamReader(System.in));

    String str;

    int n;

    double sum = 0.0;

    double avg, t;
    System.out.print("How many numbers will you enter: ");

    str = br.readLine();

    try {

    // Преобразование символьной строки

    // в числовое значение типа int.

    n = Integer.parselnt(str);

    }

    catch(NumberFormatException exc) {

    System.out.println("Invalid format");

    n = 0;

    }
    System.out.println("Enter " + n + " values.");

    for(int i=0; i < n ; i++) {

    System.out.print(" : ");

    str = br.readLine();

    try {

    // Преобразование символьной строки

    // в числовое значение типа double,

    t = Double.parseDouble(str) ;

    } catch(NumberFormatException exc) {

    System.out.println("Invalid format");

    t = 0.0;

    }

    sum += t;

    }

    avg = sum / n;

    System.out.println("Average is " + avg);

    }

    }

    Выполнение этой программы может дать, например, следующий результат:

    How many numbers will you enter: 5

    Enter 5 values.

    : 1.1

    : 2.2

    : 3.3

    : 4.4

    : 5.5

    Average is 3.3

    Примердляопробования 10.2. Создание справочной системы, находящейся на диске

    В примере для опробования 4.1 был создан класс Help, позволяющий отображать сведения об операторах Java. Справочная информация хранилась в самом классе, а пользователь выбирал требуемые сведения из меню. И хотя такая справочная система выполняет свои функции, подход к ее разработке был выбран далеко не самый лучший. Так, если требуется добавить или изменить какие-нибудь сведения в подобной справочной системе, придется внести изменения в исходный код программы, которая ее реализует. Кроме того, выбирать пункт меню по его номеру не очень удобно, а если количество пунктов велико, то такой способ оказывается вообще непригодным. В этом проекте предстоит устранить недостатки, имеющиеся в справочной системе, разместив справочную информацию на диске.

    В новом варианте справочная информация должна храниться в файле. Это будет обычный текстовый файл, который можно изменять, не затрагивая исходный код программы. Для того чтобы получить справку по конкретному вопросу, следует ввести название темы. Система будет искать соответствующий раздел в файле. Если поиск завершится успешно, справочная информация будет выведена на экран.

    Последовательность действий

    1. Создайте файл, в котором будет храниться справочная информация и который будет использоваться в справочной системе. Это должен быть обычный текстовый файл, организованный следующим образом:

    #название_темы_1

    Информация по теме
    #название_темы_2

    Информация по теме

    #название_темы_N

    Информация по теме

    1. Название каждой темы располагается в отдельной строке и предваряется символом #. Наличие специального символа в строке (в данном случае — #) позволяет программе быстро найти начало раздела. Под названием темы может располагаться любая справочная информация. После окончания одного раздела и перед началом другого должна быть введена пустая строка. Кроме того, в конце строк не должно быть лишних пробелов.

    2. Ниже приведен пример простого файла со справочной информацией, который можно использовать вместе с новой версией справочной системы. В нем хранятся сведения об операторах Java.

    #if

    if(condition) statement;

    else statement;
    #switch

    switch(expression) {

    case constant:

    statement sequence

    break;

    // ...

    }
    #for

    for(init; condition; iteration) statement;
    #while

    while(condition) statement;
    #do

    do {

    statement;

    } while (condition);
    #break

    break; or break label;
    #continue

    continue; or continue label;

    1. Присвойте этому файлу имя helpfile.txt.

    2. Создайте файл FileHelp.java.

    3. Начните создание новой версии класса Help со следующих строк кода:

    class Help {

    String helpfile; // Имя файла со справочной информацией
    Help(String fname) {

    helpfile = fname;

    }

    1. Имя файла со справочной информацией передается конструктору класса Help и запоминается в переменной экземпляра helpfile. А поскольку каждый экземпляр класса Help содержит отдельную копию переменной helpfile, то каждый из них может взаимодействовать с отдельным файлом. Это дает возможность создавать отельные наборы справочных файлов на разные темы.

    2. Добавьте в класс Help метод helpon(), код которого приведен ниже. Этот метод извлекает справочную информацию по заданной теме.

    // отобразить справочную информацию по заданной теме

    boolean helpon(String what) {

    int ch;

    String topic, info;
    // открыть справочный файл

    try (BufferedReader helpRdr =

    new BufferedReader(new FileReader(helpfile)))

    {

    do {

    // читать символы до тех пор, пока не встретится знак #

    ch = helpRdr.read();
    // а теперь проверить, совпадают ли темы

    if(ch == '#') {

    topic = helpRdr.readLine();

    if(what.compareTo(topic) == 0) { // found topic

    do {

    info = helpRdr.readLine();

    if(info != null) System.out.println(info);

    } while((info != null) &&

    (info.compareTo("") != 0));

    return true;

    }

    }

    } while(ch != -1);

    }

    catch(IOException exc) {

    System.out.println("Error accessing help file.");

    return false;

    }

    return false; // тема не найдена

    }

    1. Прежде всего обратите внимание на то, что в методе helpon() обрабатываются все исключения, связанные с вводом-выводом, поэтому в заголовке метода не указано ключевое слово throws. Благодаря такому подходу упрощается разработка методов, в которых используется метод helpon(). В вызывающем методе достаточно обратиться к методу helpon(), не заключая его вызов в блок try/catch.

    2. Для открытия файла со справочной информацией служит класс FileReader, оболочкой которого является класс BufferedReader. В справочном файле содержится текст, и поэтому справочную систему удобнее локализовать через символьные потоки ввода-вывода.

    3. Метод helpon (\ действует следующим образом. Символьная строка, содержащая название темы, передается этому методу в качестве параметра. Метод открывает сначала файл со справочной информацией. Затем в файле производится поиск, т.е. проверяется совпадение содержимого переменной what и названия темы. Напомним, что в файле заголовок темы предваряется символом #, поэтому метод сначала ищет данный символ. Если символ найден, производится сравнение следующего за ним названия темы с содержимым переменной what. Если сравниваемые строки совпадают, то отображается справочная информация по данной теме. И если заголовок темы найден, то метод helpon() возвращает логическое значение true, иначе — логическое значение false.

    4. В классе Help содержится также метод getSelectionO, который предлагает задать тему и возвращает строку, введенную пользователем.

    // получить тему

    String getSelectionO {

    String topic = "";
    BufferedReader br = new BufferedReader(

    new InputStreamReader(System.in));
    System.out.print("Enter topic: ") ;

    try {

    topic = br.readLine();

    }

    catch(IOException exc) {

    System.out.println("Error reading console.");

    }

    return topic;

    }

    1. В теле этого метода сначала создается объект типа BufferedReader, который связывается с потоком вывода System.in. Затем в нем запрашивается название темы, которое принимается и далее возвращается вызывающей части программы.

    2. Ниже приведен весь исходный код программы, реализующей справочную систему, находящуюся на диске.

    /*

    Пример для опробования 10.2.
    Справочная система, находящаяся на диске.
    Для компиляции этой программы требуется JDK 7

    или более поздняя версия данного комплекта.

    */

    import java.io.*;
    /* В классе Help открывается файл со справочной информацией,

    производится поиск названия темы, а затем отображается

    справочная информация по этой теме.

    Обратите внимание на то, что в этом классе поддерживаются

    все исключения, освобождая от этой обязанности вызывающий код. */

    class Help {

    String helpfile; // Имя файла со справочной информацией
    Help(String fname) {

    helpfile = fname;

    }
    // отобразить справочную информацию по заданной теме

    boolean helpon(String what) {

    int ch;

    String topic, info;
    // открыть справочный файл

    try (BufferedReader helpRdr =

    new BufferedReader(new FileReader(helpfile)))

    {

    do {

    // читать символы до тех пор, пока не встретится знак #

    ch = helpRdr.read();
    // а теперь проверить, совпадают ли темы

    if(ch =='#') {

    topic = helpRdr.readLine();

    if(what.compareTo(topic) == 0) { // тема найдена

    do {

    info = helpRdr.readLine();

    if(info != null) System.out.println(info);

    } while((info != null) &&

    (info.compareTo("") != 0));

    return true;

    }

    }

    } while(ch != -1);

    }

    catch(IOException exc) {

    System.out.println("Error accessing help file.");

    return false;

    }

    return false; // тема не найдена

    }
    // получить тему

    String getSelection() {

    String topic = "";
    BufferedReader br = new BufferedReader(

    new InputStreamReader(System.in));
    System.out.print("Enter topic: ");

    try {

    topic = br.readLine();

    }

    catch(IOException exc) {

    System.out.println("Error reading console.");

    }

    return topic;

    }

    }
    // продемонстрировать справочную систему, находящуюся на диске

    class FileHelp {

    public static void main(String args[]) {

    Help hlpobj = new Help("helpfile.txt");

    String topic;
    System.out.println("Try the help system. " +

    "Enter ’stop' to end.");

    do {

    topic = hlpobj.getSelection();
    if(!hlpobj.helpon(topic))

    System.out.println("Topic not found.\n");
    } while(topic.compareTo("stop") != 0);

    }

    }

    3) Отличие пакетов IO и NIO, InputStream от Reader.

    Когда я начал изучать стандартный ввод/вывод в Java, то первое время был немного шокирован обилием интерфейсов и классов пакета java.io.*, дополненных еще и целым перечнем специфических исключений.

    Потратив изрядное количество часов на изучение и реализацию кучи разнообразных туториалов из Интернета, начал чувствовать себя уверенно и вздохнул с облегчением. Но в один прекрасный момент понял, что для меня все только начинается, так как существует еще и пакет java.nio.*, известный ещё под названием Java NIO или Java New IO. Вначале казалось, что это тоже самое, ну типа вид сбоку. Однако, как оказалось, есть существенные отличия, как в принципе работы, так и в решаемых с их помощью задачах.

    Разобраться во всем этом мне здорово помогла статья Джакоба Дженкова (Jakob Jenkov) – “Java NIO vs. IO”. Ниже она приводиться в адаптированном виде.

    Поспешу заметить, что статья не является руководством по использованию Java IO и Java NIO. Её цель – дать людям, начинающим изучать Java, возможность понять концептуальные отличия между двумя указанными инструментами организации ввода/вывода.
    Основные отличия между Java IO и Java NIO


    IO

    NIO

    Потокоориентированный

    Буфер-ориентированный

    Блокирующий (синхронный) ввод/вывод

    Неблокирующий (асинхронный) ввод/вывод




    Селекторы

    Потокоориентированный и буфер-ориентированный ввод/вывод


    Основное отличие между двумя подходами к организации ввода/вывода в том, что Java IO является потокоориентированным, а Java NIO – буфер-ориентированным. Разберем подробней.

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

    Потокоориентированный ввод:



    Потокоориентированный вывод:



    Подход, на котором основан Java NIO немного отличается. Данные считываются в буфер для последующей обработки. Вы можете двигаться по буферу вперед и назад. Это дает немного больше гибкости при обработке данных. В то же время, вам необходимо проверять содержит ли буфер необходимый для корректной обработки объем данных. Также необходимо следить, чтобы при чтении данных в буфер вы не уничтожили ещё не обработанные данные, находящиеся в буфере.
    Блокирующий и неблокирующий ввод/вывод


    Потоки ввода/вывода (streams) в Java IO являются блокирующими. Это значит, что когда в потоке выполнения (tread) вызывается read() или write() метод любого класса из пакета java.io.*, происходит блокировка до тех пор, пока данные не будут считаны или записаны. Поток выполнения в данный момент не может делать ничего другого.

    Неблокирующий режим Java NIO позволяет запрашивать считанные данные из канала (channel) и получать только то, что доступно на данный момент, или вообще ничего, если доступных данных пока нет. Вместо того, чтобы оставаться заблокированным пока данные не станут доступными для считывания, поток выполнения может заняться чем-то другим.

    Каналы (channels)

    Каналы – это логические (не физические) порталы, через которые осуществляется ввод/вывод данных, а буферы являются источниками или приёмниками этих переданных данных. При организации вывода, данные, которые вы хотите отправить, помещаются в буфер, а он передается в канал. При вводе, данные из канала помещаются в предоставленный вами буфер.

    Каналы напоминают трубопроводы, по которым эффективно транспортируются данные между буферами байтов и сущностями по ту сторону каналов. Каналы – это шлюзы, которые позволяют получить доступ к сервисам ввода/вывода операционной системы с минимальными накладными расходами, а буферы – внутренние конечные точки этих шлюзов, используемые для передачи и приема данных.


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

    Таким образом неблокирующий режим Java NIO позволяет использовать один поток выполнения для решения нескольких задач вместо пустого прожигания времени на ожидание в заблокированном состояний. Наиболее частой практикой является использование сэкономленного времени работы потока выполнения на обслуживание операций ввода/вывода в другом или других каналах.
    Селекторы


    Селекторы в Java NIO позволяют одному потоку выполнения мониторить несколько каналов ввода. Вы можете зарегистрировать несколько каналов с селектором, а потом использовать один поток выполнения для обслуживания каналов, имеющих доступные для обработки данные, или для выбора каналов, готовых для записи.

    Чтобы лучше понять концепцию и выгоду от применения селекторов, давайте абстрагируемся от программирования и представим себе железнодорожный вокзал. Вариант без селектора: есть три железнодорожных пути (каналы), на каждый из них в любой момент времени может прибыть поезд (данные из буфера), на каждом пути постоянно ожидает сотрудник вокзала (поток выполнения), задача которого – обслуживание прибывшего поезда. В результате трое сотрудников постоянно находятся на вокзале даже если там вообще нет поездов. Вариант с селектором: ситуация та же, но для каждой платформы есть индикатор, сигнализирующий сотруднику вокзала (поток выполнения) о прибытии поезда. Таким образом на вокзале достаточно присутствия одного сотрудника.
    Влияние Java NIO и Java IO на дизайн приложения


    Выбор между Java NIO и Java IO может на следующие аспекты дизайна вашего приложения:
    1. API обращений к классам ввода/вывода;
    2. Обработка данных;
    3. Количество потоков выполнения, использованных для обработки данных.
    API обращений к классам ввода/вывода


    Естественно, использование Java NIO серьезно отличается от использования Java IO. Так как, вместо чтения данных байт за байтом с использованием, например InputStream, данные для начала должны быть считаны в буфер и браться для обработки уже оттуда.
    Обработка данных


    Обработка данных при использовании Java NIO тоже отличается.
    Как уже упоминалось, при использовании Java IO вы читаете данные байт за байтом с InputStream или Reader. Представьте, что вы проводите считывание строк текстовой информации:

    Name: Anna
    Age: 25
    Email: anna@mailserver.com
    Phone: 1234567890

    Этот поток строк текста может обрабатываться следующим образом:
    InputStream input = ... ;

    BufferedReader reader = new BufferedReader(new InputStreamReader(input));

    String nameLine = reader.readLine();

    String ageLine = reader.readLine();

    String emailLine = reader.readLine();

    String phoneLine = reader.readLine();


    Обратите внимание, как состояние процесса обработки зависит от того, насколько далеко продвинулось выполнение программы. Когда первый метод readLine() возвращает результат выполнения, вы уверенны – целая строка текста была считана. Метод является блокирующим и действие блокировки продолжается до тех пор, пока вся строка не будет считана. Вы также четко понимаете, что данная строка содержит имя. Подобно этому, когда метод вызывается во второй раз, вы знаете, что в результате получите возраст.

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



    Имплементация с использованием Java IO будет выглядеть несколько иначе:
    ByteBuffer buffer = ByteBuffer.allocate(48);

    int bytesRead = inChannel.read(buffer);


    Обратите внимание на вторую строчку кода, в которой происходит считывание байтов из канала в ByteBuffer. Когда возвращается результат выполнения данного метода, вы не можете быть уверенны, что все необходимые вам данные находятся внутри буфера. Все, что вам известно, так это то, что буфер содержит некоторые байты. Это немного усложняет процесс обработки.

    Представьте, что после первого вызова метода read(buffer), в буфер было считано только половину строки. Например, “Name: An”. Сможете ли вы обработать такие данные? Наверное, что нет. Вам придется ждать пока, по крайней мере, одна полная строка текста не будет считана в буфер.

    Так как же вам узнать, достаточно ли данных для корректной обработки содержит буфер? А никак. Единственный вариант узнать, это посмотреть на данные, содержащиеся внутри буфера. В результате вам придется по нескольку раз проверять данные в буфере, пока они не станут доступными для корректной обработки. Это неэффективно и может негативно сказаться на дизайне программы. Например:
    ByteBuffer buffer = ByteBuffer.allocate(48);

    int bytesRead = inChannel.read(buffer);

    while(! bufferFull(bytesRead) ) {

    bytesRead = inChannel.read(buffer);

    }

    Метод bufferFull() должен следить за тем, сколько данных считано в буфер и возвращать true или false, в зависимости от того, заполнен буфер или нет. Другими словами, если буфер готов к обработке, то он считается заполненным.

    Также метод bufferFull() должен оставлять буфер в неизмененном состоянии, поскольку в противном случае следующая порция считанных данных может быть записана в неправильное место.

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

    Следующая схема демонстрирует процесс определения готовности данных в буфере для корректной обработки:


    Итоги


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

    Если вам необходимо управлять тысячами открытых соединений одновременно, причем каждое из них передает лишь незначительный объем данных, выбор Java NIO для вашего приложения может дать преимущество. Дизайн такого типа схематически изображен на следующем рисунке:



    Если вы имеете меньшее количество соединений, по которым передаются большие объемы данных, то лучшим выбором станет классический дизайн системы ввода/вывода:



    Важно понимать, что Java NIO отнюдь не является заменой Java IO. Его стоит рассматривать как усовершенствование – инструмент, позволяющий значительно расширить возможности по организации ввода/вывода. Грамотное использование мощи обоих подходов позволит вам строить хорошие высокопроизводительные системы.

    Стоит заметить, что с выходом версии Java 1.7 появился еще и Java NIO.2, но присущие ему новшества касаются, в первую очередь, работы с файловым вводом/выводом, поэтому выходят за рамки этой статьи.

    PS: также в данном посте использованы материалы очень достойной статьи Nino Guarnacci – «Java.nio vs Java.io»
    Класс Reader — это полный аналог класса InputStream, с одним только отличием: он работает с символами — char, а не с байтами. Класс Reader, так же, как и класс InputStream самостоятельно нигде не используется: он является классом-родителем для сотен классов-наследников и задает для них всех общие методы.

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

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

    Вы можете обернуть InputStream и превратить его в Reader с помощью класса InputStreamReader.

    Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    Я предполагаю, что источник путаницы в том, что InputStream.read() возвращает int и Reader.read() также возвращает int.

    Разница в том, что InputStream.read() возвращать байтовые значения от 0 до 255, соответствующие необработанному содержимому байтового потока и Reader.read() вернуть значение символа, которое находится между 0 и 65357 (потому что существует 65358 различных кодовых точек Unicode)

    An InputStream позволяет читать содержимое побайтно, например, содержимое «a ‡ a» состоит из 3 символов, но закодировано 5 байтами в UTF-8. Так что с Inputstream вы можете прочитать его как поток из 5 байтов (каждый из которых представлен как int от 0 до 255), что приводит к 97226128161 и 97 в котором

    a -> U+0061 -> 0x61 (hex) -> 97 (dec)

    ‡ -> U+2021 -> 0xE280A1 (utf-8 encoding of 0x2021) -> 226 128 161 (1 int per byte)

    a -> U+0061 -> 0x61 (hex) -> 97 (dec)

    Reader позволяет читать содержимое посимвольно, поэтому содержимое «a ‡ a» читается как 3 символа 978225 и 97 в котором

    a -> U+0061 -> 0x61 -> 97

    ‡ -> U+2021 -> 0x2021 -> 8225 (single int, not 3)

    a -> U+0061 -> 0x61 -> 97
    4) как работает метод read?

    Метод read () читает один байт из потока и возвращает его. Вас может сбить тип результата — int, однако так было сделано, потому что тип int — это стандарт всех целых чисел. Три первые байта типа int будут равны нулю. Метод read (byte [] buffer). Это вторая модификация метода read (). Он позволяет считать из InputStream сразу массив байт. Массив для сохранения байт нужно передать в качестве параметра.

    Как же все-таки устроена работа метода read():

    1. Почему метод возвращает int а не byte?

    2. Почему возвращается byte как int в диапазоне от 0 до 255?

    3. Почему метод не может возвращать byte?

    4. Что вернет метод если он считает -1 из входного потока?



    1   ...   10   11   12   13   14   15   16   17   ...   39


    написать администратору сайта