컴퓨터의 내부 또는 외부 장치와 프로그램 간의 데이터 교환
자바에서 IO를 위해 java.io 패키지에 다양한 클래스들을 제공함

데이터가 단방향으로 연속적으로 흐르는 것을 의미함
1byte 단위로 데이터를 전송하는 스트림
package java.io;
public abstract class InputStream implements Closeable {
...
public abstract int read() throws IOException;
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
public int read(byte[] b, int off, int len) throws IOException {
... // read() 메소드 사용됨
}
...
}

byte[] b)byte[] b, int off, int len)public class InputStreamExam {
public static void main(String[] args) throws IOException {
byte[] byteData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
ByteArrayInputStream is;
int readData;
int numberOfReadData;
// read()
System.out.println("============read()============");
is = new ByteArrayInputStream(byteData);
while ((readData = is.read()) != -1) {
System.out.println("readData = " + readData);
}
/**
* readData = 0
* readData = 1
* readData = 2
* readData = 3
* readData = 4
* readData = 5
* readData = 6
* readData = 7
* readData = 8
* readData = 9
*/
// read(byte[] b)
System.out.println("============read(byte[] b)============");
is = new ByteArrayInputStream(byteData);
byte[] buffer = new byte[3];
while ((numberOfReadData = is.read(buffer)) != -1) {
System.out.println("numberOfReadData = " + numberOfReadData);
// 읽은 데이터의 갯수를 고려해서 출력
for (int count = 0; count < numberOfReadData; count++) {
System.out.println("data = " + buffer[count]);
}
}
/**
* numberOfReadData = 3
* data = 0
* data = 1
* data = 2
* numberOfReadData = 3
* data = 3
* data = 4
* data = 5
* numberOfReadData = 3
* data = 6
* data = 7
* data = 8
* numberOfReadData = 1
* data = 9
*/
// read(byte[] b, int off, int len)
System.out.println("============read(byte[] b, int off, int len)============");
is = new ByteArrayInputStream(byteData);
byte[] bytes = new byte[5];
numberOfReadData = is.read(bytes, 2, 3);
System.out.println("numberOfReadData = " + numberOfReadData);
for (byte data : bytes) {
System.out.println("data = " + data);
}
/**
* numberOfReadData = 3
* data = 0
* data = 0
* data = 0
* data = 1
* data = 2
*/
}
}package java.io;
public abstract class OutputStream implements Closeable, Flushable {
...
public abstract void write(int b) throws IOException;
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
// len == 0 condition implicitly handled by loop bounds
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}

byte[] b)byte[] b, int off, int len)public class OutputStreamExam {
public static void main(String[] args) throws IOException {
byte[] byteData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
ByteArrayOutputStream os;
// write(int b)
System.out.println("============write(int b)============");
os = new ByteArrayOutputStream();
os.write('a');
os.write('b');
os.write('c');
byte[] writtenByteData = os.toByteArray();
for (byte writtenData : writtenByteData) {
System.out.println("writtenData = " + (char) writtenData);
}
/**
* writtenData = a
* writtenData = b
* writtenData = c
*/
// write(byte[] b)
System.out.println("============write(byte[] b)============");
os = new ByteArrayOutputStream();
os.write(byteData);
writtenByteData = os.toByteArray();
for (byte writtenData : writtenByteData) {
System.out.println("writtenData = " + writtenData);
}
/**
* writtenData = 0
* writtenData = 1
* writtenData = 2
* writtenData = 3
* writtenData = 4
* writtenData = 5
* writtenData = 6
* writtenData = 7
* writtenData = 8
* writtenData = 9
*/
// write(byte[] b, int off, int len)
System.out.println("============write(byte[] b, int off, int len)============");
os = new ByteArrayOutputStream();
os.write(byteData, 5, 3);
writtenByteData = os.toByteArray();
for (byte writtenData : writtenByteData) {
System.out.println("writtenData = " + writtenData);
}
/**
* writtenData = 5
* writtenData = 6
* writtenData = 7
*/
}
}InputStream, OutputStream을 직접 상속받지만, 기반 스트림을 필요로 하는 보조 스트림