# Input/Output

In [programming](programming.md) input/output (I/O or just IO) refers to communication of a computer [program](program.md) with the outside environment, for example with the [user](user.md) in [real world](irl.md) or with the [operating system](os.md). Input is [information](information.md) the program gets from the outside, output is information the program sends to the outside. I/O is a basic and very important term as it separates any program to two distinct parts: the pure [computational system](computational_system.md) (computation happening "inside") and I/O which interconnects this system with the real world and hence makes it useful -- without I/O a program would be practically useless as it couldn't get any information about the real world and it couldn't present computed results. In [hardware](hardware.md) there exists the term "I/O device", based on the same idea -- I/O devices serve to feed input into and/or get output from a physical [computer](computer.md), for example keyboard is an input device and monitor is an output device (a computer without I/O devices would be useless just as a program without I/O operations).

Note that I/O is not just about communication with a human user, it also means e.g. communication over [network](network.md), reading/writing from/to [files](file.md) etc.

It is possible to have no input (e.g. a [demo](demoscene.md)), but having no output at all probably makes no sense (see also [write-only](write_only.md)).

**I/O presents a challenge for [portability](portability.md)!** While the "pure computation" part of a program may be written in a pure platform-independent language such as [C](c.md) (and can therefore easily be compiled on different computers) and may be quite [elegant](elegance.md), the I/O part gets more ugly.

This is because **I/O is inevitably messy**: an abstract, portable I/O library really tries to do the impossible task of unifying all wildly differing physical computers and their architectures under some simple functions; for example consider an I/O library will offer a function such as `drawPixel(x,y,color)` that draws a pixel to the screen -- how do we make this work for all computers? What value is *color* here, is it RGB, a color index, HDR value? What if a computer doesn't allow writing to arbitrary parts of screen coordinates because it lack a frame buffer, or what if such operation is painfully slow there (some computers may just want to write pixels sequentially in possibly varying orders we can't predict)? WHAT IF the computer doesn't even have a raster screen but instead has a [vector](vector.md) screen? Even such things as files residing in a tree of directories are something that's highly established but not necessarily the only way a computer may work, some computers may for example support files but not directories, how does our library take this into account? How do we deal with file names with very weird characters, what if someone makes a file system where file names are actually [rich text](rich_text.md) or where files aren't places in directories but are rather points in [3D](3d.md) space or something? So an I/O library has to inevitably make many assumptions about what a "normal" computer looks like and what will likely help it operate fast etc. It has to decide how to deal with unsupported things, for example if we try to display color on a black and white display will it cause an error or will we try to somehow approximate the color just with shades of gray? And of course with new I/O devices appearing (VR, brain interfaces, ...) the library will have to be constantly [updated](update_culture.md). So the I/O part of the program will usually require some platform specific [library](library.md) or a library with many [dependencies](dependency.md); for example to display pictures on screen one may use [SDL](sdl.md), [OpenGL](opengl.md), Linux framebuffer, CSFML, [X11](x11.md), [Wayland](wayland.md) and many other libraries, each one handling I/O a bit differently. Whatever library you choose, it may be unavailable on some other platform, so the program won't run there. Some hardware platforms (e.g. many game consoles) even have their own exclusive I/O library, use of which will just tie the program to that single platform. There are programming languages and libraries that try to provide platform-independent I/O, but as said such approach is limited as it has to assume some common features that will be available everywhere; for example [C](c.md) has a standard platform-independent I/O library *stdio*, but it only allows text and binary input/output, for anything advanced such as graphics, sound and mouse one has to choose some 3rd party library. [Unix philosophy](unix_philosophy.md) also advises to only use text I/O if possible, so as to "standardize" and tame I/O a bit, but then again one has to choose what communication [protocol](protocol.md)/format to use etc., so the problem just shifts from standardizing library API to standardizing protocols. So generally I/O is a problem we have to deal with.

How to solve this? By separating I/O code from the "pure computation" code, and by minimizing and [abstracting](abstraction.md) the I/O code so that it is easily replaceable. Inexperienced programmers often make the mistake of mixing the pure computation code with I/O code -- it is then very difficult to replace such I/O code with different I/O code on a different platform. See [portability](portability.md) for more detail. Also if you don't have to, **avoid I/O altogether**, especially if your project is a library -- for example if you're writing a 3D rendering library, you do NOT actually need any I/O, your library will simply be computing which pixels to draw and what color they should have, the library doesn't actually have to write those pixels to any screen, this may be left to the user of the library (this is exactly how [small3dlib](small3dlib.md) works).

I/O also poses problems in some programming [paradigms](paradigm.md), e.g. in [functional programming](functional.md).

TODO: code example