Kotlin Standard Input Output

Kotlin standard input output (I/O) refers to the process of reading data from input devices like keyboards and displaying information to output devices such as monitors. In Kotlin programming, input output operations enable your programs to interact with users by accepting data, processing it, and presenting results in a meaningful way.

The Kotlin input output system operates through byte streams that flow between devices and your program’s memory. When you type on a keyboard, that input becomes a stream of data that your Kotlin application can capture and process using specific functions designed for this purpose.

Essential Kotlin Output Functions

The println() Function

The println() function is the most commonly used output function in Kotlin. It prints text to the console and automatically moves the cursor to the next line.

fun main() {  
    println("Welcome to Kotlin programming!")  
    println("This is a new line")  
}  

Key characteristics of println():

  • Automatic line break: Adds a newline character after printing
  • String interpolation support: Can display variables using $variable syntax
  • Internal implementation: Calls System.out.println() from Java internally
  • Versatile data handling: Accepts any data type and converts it to string representation

The print() Function

The print() function displays text without adding a line break, keeping subsequent output on the same line.

fun main() {  
    print("Hello ")  
    print("World!")  
    println() // Adds line break manually  
    print("Kotlin ")  
    print("is ")  
    print("awesome!")  
}  

print() function properties:

  • No automatic line break: Output continues on same line
  • Flexible formatting: Allows precise control over text positioning
  • Performance: Slightly faster than println() for continuous output
  • Java compatibility: Uses System.out.print() underneath

String Interpolation in Output

Kotlin’s string interpolation makes displaying variables and expressions incredibly easy and readable.

fun main() {  
    val name = "Alice"  
    val age = 25  
    val score = 87.5  
      
    println("Student name: $name")  
    println("Age: $age years old")  
    println("Average score: $score")  
    println("Next year age: ${age + 1}")  
    println("Grade: ${if (score >= 90) "A" else "B"}")  
}  

String interpolation features:

  • Simple variables: Use $variableName for direct variable insertion
  • Complex expressions: Use ${expression} for calculations and function calls
  • Type safety: Automatically converts different data types to strings
  • Performance optimization: More efficient than string concatenation

Kotlin Input Functions: Modern Approaches

The readln() Function (Recommended)

Introduced in Kotlin 1.6.0, readln() is the modern, preferred method for reading console input. It returns a non-null string and throws an exception if input is unavailable.

fun main() {  
    println("Enter your name:")  
    val name = readln()  
    println("Hello, $name!")  
      
    println("Enter your age:")  
    val age = readln().toInt()  
    println("You are $age years old")  
}  

readln() advantages:

  • Non-null guarantee: Returns String instead of String?
  • Modern API: Follows Kotlin’s current naming conventions
  • Simplified code: Eliminates need for null checks in most cases
  • Exception handling: Throws IllegalStateException for invalid input

Converting Input to Different Data Types

The readln() function always returns a string, but you can convert it to other data types using conversion functions.

fun main() {  
    // Reading different data types  
    println("Enter an integer:")  
    val intValue = readln().toInt()  
      
    println("Enter a decimal number:")  
    val doubleValue = readln().toDouble()  
      
    println("Enter true or false:")  
    val booleanValue = readln().toBoolean()  
      
    println("Enter a floating-point number:")  
    val floatValue = readln().toFloat()  
      
    println("Results:")  
    println("Integer: $intValue")  
    println("Double: $doubleValue")  
    println("Boolean: $booleanValue")  
    println("Float: $floatValue")  
}  

Available conversion functions:

  • toInt(): Converts string to integer
  • toDouble(): Converts string to double-precision floating point
  • toFloat(): Converts string to single-precision floating point
  • toLong(): Converts string to long integer
  • toBoolean(): Converts string to boolean value

Safe Input Conversion with toIntOrNull()

For robust applications, use safe conversion functions that return null instead of throwing exceptions for invalid input.

fun main() {  
    println("Enter a number:")  
    val input = readln()  
    val number = input.toIntOrNull()  
      
    if (number != null) {  
        println("Valid number: $number")  
        println("Double the number: ${number * 2}")  
    } else {  
        println("Invalid input: '$input' is not a valid number")  
    }  
}  

Safe conversion methods:

  • toIntOrNull(): Returns null for invalid integers
  • toDoubleOrNull(): Returns null for invalid doubles
  • toFloatOrNull(): Returns null for invalid floats
  • toLongOrNull(): Returns null for invalid longs

Reading Multiple Values

You can read multiple values from a single line of input using string manipulation functions.

fun main() {  
    println("Enter three numbers separated by spaces:")  
    val numbers = readln().split(' ').map { it.toInt() }  
      
    println("First number: ${numbers[0]}")  
    println("Second number: ${numbers[1]}")  
    println("Third number: ${numbers[2]}")  
    println("Sum: ${numbers.sum()}")  
      
    println("Enter comma-separated words:")  
    val words = readln().split(',').map { it.trim() }  
    println("Words: $words")  
}  

Scanner Class for Advanced Input Operations

While readln() is preferred for simple input operations, the Java Scanner class provides more sophisticated input handling capabilities.

Setting Up Scanner

import java.util.Scanner  
  
fun main() {  
    val scanner = Scanner(System.`in`)  
      
    println("Enter your details:")  
    print("Name: ")  
    val name = scanner.nextLine()  
      
    print("Age: ")  
    val age = scanner.nextInt()  
      
    print("Height (in meters): ")  
    val height = scanner.nextDouble()  
      
    println("\nProfile Summary:")  
    println("Name: $name")  
    println("Age: $age")  
    println("Height: $height meters")  
      
    scanner.close()  
}  

Scanner Methods for Different Data Types

The Scanner class provides specific methods for reading different data types directly.

import java.util.Scanner  
  
fun main() {  
    val scanner = Scanner(System.`in`)  
      
    // Reading different types  
    print("Enter an integer: ")  
    val intValue = scanner.nextInt()  
      
    print("Enter a float: ")  
    val floatValue = scanner.nextFloat()  
      
    print("Enter a boolean: ")  
    val booleanValue = scanner.nextBoolean()  
      
    // Clear the buffer before reading string  
    scanner.nextLine()  
      
    print("Enter a line of text: ")  
    val textLine = scanner.nextLine()  
      
    print("Enter a single word: ")  
    val word = scanner.next()  
      
    println("\nResults:")  
    println("Integer: $intValue")  
    println("Float: $floatValue")  
    println("Boolean: $booleanValue")  
    println("Text line: $textLine")  
    println("Word: $word")  
      
    scanner.close()  
}  

Scanner method reference:

  • nextInt(): Reads the next integer
  • nextFloat(): Reads the next float
  • nextDouble(): Reads the next double
  • nextBoolean(): Reads the next boolean
  • nextLine(): Reads entire line including spaces
  • next(): Reads next token (stops at whitespace)

Scanner with Custom Delimiters

Scanner allows you to specify custom delimiters for parsing input.

import java.util.Scanner  
  
fun main() {  
    val scanner = Scanner(System.`in`)  
      
    println("Enter numbers separated by commas:")  
    scanner.useDelimiter(",")  
      
    val numbers = mutableListOf<Int>()  
    while (scanner.hasNextInt()) {  
        numbers.add(scanner.nextInt())  
    }  
      
    println("Numbers entered: $numbers")  
    println("Sum: ${numbers.sum()}")  
    println("Average: ${numbers.average()}")  
      
    scanner.close()  
}  

Error Handling in Input Operations

Proper error handling is crucial for creating robust Kotlin applications that can handle unexpected user input gracefully.

Exception Handling with readln()

fun main() {  
    var validInput = false  
    var number = 0  
      
    while (!validInput) {  
        try {  
            println("Enter a valid integer:")  
            number = readln().toInt()  
            validInput = true  
        } catch (e: NumberFormatException) {  
            println("Error: Please enter a valid integer!")  
        }  
    }  
      
    println("You entered: $number")  
    println("Square: ${number * number}")  
}  

Scanner Error Handling

import java.util.Scanner  
import java.util.InputMismatchException  
  
fun main() {  
    val scanner = Scanner(System.`in`)  
      
    try {  
        print("Enter your age: ")  
        val age = scanner.nextInt()  
          
        if (age < 0) {  
            println("Age cannot be negative!")  
        } else {  
            println("You are $age years old")  
        }  
          
    } catch (e: InputMismatchException) {  
        println("Error: Please enter a valid number!")  
    } finally {  
        scanner.close()  
    }  
}  

Complete Example Programs

Interactive Calculator

import java.util.Scanner  
  
fun main() {  
    val scanner = Scanner(System.`in`)  
    var continueCalculating = true  
      
    println("=== Kotlin Calculator ===")  
      
    while (continueCalculating) {  
        try {  
            println("\nEnter first number:")  
            val num1 = readln().toDouble()  
              
            println("Enter operator (+, -, *, /):")  
            val operator = readln()  
              
            println("Enter second number:")  
            val num2 = readln().toDouble()  
              
            val result = when (operator) {  
                "+" -> num1 + num2  
                "-" -> num1 - num2  
                "*" -> num1 * num2  
                "/" -> {  
                    if (num2 != 0.0) {  
                        num1 / num2  
                    } else {  
                        println("Error: Division by zero!")  
                        continue  
                    }  
                }  
                else -> {  
                    println("Error: Invalid operator!")  
                    continue  
                }  
            }  
              
            println("Result: $num1 $operator $num2 = $result")  
              
            println("\nContinue? (y  
):")  
            val choice = readln().lowercase()  
            continueCalculating = choice == "y" || choice == "yes"  
              
        } catch (e: NumberFormatException) {  
            println("Error: Please enter valid numbers!")  
        }  
    }  
      
    println("Thank you for using Kotlin Calculator!")  
}  

Student Grade Management System

fun main() {  
    println("=== Student Grade Management ===")  
      
    println("Enter student name:")  
    val studentName = readln()  
      
    println("Enter number of subjects:")  
    val subjectCount = readln().toInt()  
      
    val grades = mutableListOf<Double>()  
    val subjects = mutableListOf<String>()  
      
    for (i in 1..subjectCount) {  
        println("Enter subject $i name:")  
        val subject = readln()  
        subjects.add(subject)  
          
        println("Enter grade for $subject:")  
        val grade = readln().toDouble()  
        grades.add(grade)  
    }  
      
    val average = grades.average()  
    val total = grades.sum()  
      
    println("\n=== Grade Report ===")  
    println("Student: $studentName")  
    println("Subjects and Grades:")  
      
    for (i in subjects.indices) {  
        println("${subjects[i]}: ${grades[i]}")  
    }  
      
    println("\nTotal Points: $total")  
    println("Average: %.2f".format(average))  
      
    val letterGrade = when {  
        average >= 90 -> "A"  
        average >= 80 -> "B"  
        average >= 70 -> "C"  
        average >= 60 -> "D"  
        else -> "F"  
    }  
      
    println("Letter Grade: $letterGrade")  
      
    val status = if (average >= 60) "PASSED" else "FAILED"  
    println("Status: $status")  
}  

Number Guessing Game

import kotlin.random.Random  
  
fun main() {  
    println("=== Number Guessing Game ===")  
    println("I'm thinking of a number between 1 and 100!")  
      
    val secretNumber = Random.nextInt(1, 101)  
    var attempts = 0  
    var hasWon = false  
    val maxAttempts = 7  
      
    while (attempts < maxAttempts && !hasWon) {  
        attempts++  
        println("\nAttempt $attempts/$maxAttempts")  
        println("Enter your guess:")  
          
        try {  
            val guess = readln().toInt()  
              
            when {  
                guess < 1 || guess > 100 -> {  
                    println("Please enter a number between 1 and 100!")  
                    attempts-- // Don't count invalid input as an attempt  
                }  
                guess < secretNumber -> {  
                    println("Too low! Try a higher number.")  
                }  
                guess > secretNumber -> {  
                    println("Too high! Try a lower number.")  
                }  
                else -> {  
                    hasWon = true  
                    println("🎉 Congratulations! You guessed it!")  
                    println("The number was $secretNumber")  
                    println("You won in $attempts attempts!")  
                }  
            }  
        } catch (e: NumberFormatException) {  
            println("Please enter a valid number!")  
            attempts-- // Don't count invalid input as an attempt  
        }  
    }  
      
    if (!hasWon) {  
        println("\n😞 Game Over! You've used all $maxAttempts attempts.")  
        println("The secret number was $secretNumber")  
    }  
      
    println("\nThanks for playing!")  
}  

Key Differences: readln() vs Scanner vs readLine()

Featurereadln()ScannerreadLine()
Return TypeStringVarious typesString?
Null SafetyNon-nullType-specificNullable
PerformanceFastSlowerFast
Type ConversionManualAutomaticManual
Error HandlingExceptionExceptionNull return
Recommended UseModern KotlinAdvanced parsingLegacy code