Путаница в DataInputStream

Почему, когда этот фрагмент кода выполняется, если вы вводите «3» в качестве ввода, он не пишет «Печать» в консоль, а «33» записывает «Печать»?

public static void main(String[] args) throws Exception
{
    DataInputStream input;
    int any;

    input = new DataInputStream(System.in);
    any = input.readInt();
    System.out.println("Print");
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
63
2

Ответы 2

Потому что InputStream читается как byte, а не как char.

readInt будет читать 4 byte, чтобы построить int. Но ваш вход 3 имеет только 1 byte (0x33). Добавьте разделитель строк (\ r \ n) (0x0d0a), есть только 3 byte, которые не могут построить int. Вы можете попробовать войти еще раз, он будет распечатан.

Но правильный способ - читать char как char way. Вы можете использовать Reader или Scanner

input = new Scanner(System.in);
i = input.nextInt();

@mewkie Я сказал, что есть разделитель строк (0x0d0a). Вы можете распечатать свой any, это не 33, а (0x33330d0a).

Dean Xu 25.03.2018 04:34

Нажатие Enter на клавиатуре добавляет символ новой строки \n при появлении запроса на ввод. По этой причине ввод 333 и нажатие Enter дает следующее значение, сохраненное в any: 858993418.

Глядя на исходный код DataInputStream#readInt, мы видим следующее:

public final int readInt() throws IOException {
    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

Следовательно, мы можем рассчитать any следующим образом:

('3' << 24) + ('3' << 16) + ('3' << 8) + '\n'

Я не уверен, почему вы говорите, что 33 работает, потому что ввод только 33 и нажатие Enter не дает DataInputStream четырех байтов, поэтому он продолжает ждать следующего байта. Вы можете дважды нажать Enter, и он будет распечатан. Ваша IDE может добавлять возврат каретки \r, а также символ новой строки \r, поэтому 33 будет работать для вас, а не для меня в Intellij.

Это хорошее объяснение происходящего. Если вы хотите просто прочитать число, которое пользователь вводит перед <enter>, лучше всего использовать BufferedReader.readLine() для получения ввода в виде строки, а затем использовать String.valueOf для преобразования этой строки в целое число.

lsowen 25.03.2018 20:15

Спасибо, OP должен просто использовать Scanner;)

Jacob G. 25.03.2018 20:15

Ооо, хороший момент, гораздо лучше использовать Scanner

lsowen 25.03.2018 20:18

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