표준입출력 - System.in, System.out, System.err

표준입출력은 콘솔(console, 도스창)을 통한 데이터 입력과 콘솔로의 데이터 출력을 의미한다. 자바에서는 표준 입출력(standard I/O)을 위해 3가지 입출력 스트림, System.in, System.out, System.err을 제공하는데, 이 들은 자바 어플리케이션의 실행과 동시에 사용할 수 있게 자동적으로 생성되기 때문에 개발자가 별도의 스트림을 생성하는 코드를 작성하지 않고도 사용이 가능하다.

System.in 콘솔로부터 데이터를 입력받는데 사용
System.out 콘솔로 데이터를 출력하는데 사용
System.err 콘솔로 데이터를 출력하는데 사용

 

System클래스의 소스에서 알 수 있듯이, in, out, err은 System클래스에 선언된 클래스변수(static변수)이다. 선언부분만을 봐서는 out, err, in의 타입은 InputStream과 PrintStream이지만 실제로는 버퍼를 이용하는 BufferedInputStream과 BufferedOutputStream을 사용한다(속도가 빠르다)

public final class System {
	public final static InputStream in = nullInputStream();
	public final static PrintStream out = nullPrintStream();
	public final static PrintStream err = nullPrintStream();
	...
}

Editplus나 이클립스와 같은 에디터에서는 콘솔로의 출력을 중간에 가로채서 에디터에 뿌려주는 것이다. Editplus의 설정화면에서 'Capture Output'옵션을 선택하면 콘솔에 출력하는 내용이 Editplus의 하단에 출력된다.

 

 

public class StandardIOEx1 {
	public static void main(String[] args) {
		try {
			int input = 0;

			while ((input = System.in.read()) != -1) {
				System.out.println("input :" + input + ", (char)input : " + (char) input);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

콘솔입력은 버퍼를 가지고 있기 때문에 Backspace키를 이용해서 편집이 가능하며 한 번에 버퍼의 크기만큼 입력이 가능하다.

콘솔에 데이터를 입력하고 Enter키를 누르면 입력대기상태에서 벗어나 입력된 데이터를 읽기 시작하고 입력된 데이터를 모두 읽으면 다시 입력대기 상태가 된다.

이러한 과정이 반복되다가 사용자가 ctrl+z를 입력하면, read()는 입력이 종료되었음을 인식하고 -1을 반환하여 while문을 벗어나 프로그램이 종료된다.

enter키를 두개 누르는 것은 두 개의 특수문자'\r'과'\n'이 입력된 것으로 간주된다. '\r'은 캐리지리턴(carriage return), 즉 커서를 현재 라인의 첫 번째 컬럼으로 이동시키고'\n'은 커서를 다음 줄로 이동시키는 줄바꿈(new line)을 한다.

그래서 Enter키를 누르면, 캐리지리턴과 줄바꿈이 수행되어 다음 줄의 첫 번째 칼럼으로 커서가 이동하는 것이다.

 

 

 

표준입출력 대상변경 - setOut(), setErr(), setln()

초기에는 System.in, System.out, System.err의 입출력대상이 콘솔화면이지만, setln(), setOut(), setErr()를 사용하면 입출력을 콘솔 이외에 다른 입출력 대상으로 변경하는 것이 가능하다.

 

메서드 설명
static void setOut(PrintStream out) System.out의 출력을 지정된 PrintStream으로 변경
static void setErr(PrintStream err) System.err의 출력을 지정한 PrintStream으로 변경
static void setln(InputStream in) System.in의 입력을 지정한 InputStream으로 변경

 

public class StandardIOEx2 {
	public static void main(String[] args) {
		System.out.println("out : Hello World!");
		System.err.println("err : Hello World!");
	}
}

 

 

 

RandomAccessFile

자바에서는 입력과 출력이 각각 분리되어 별도로 작업을 하도록 설계되어 있는데 RandomAccessFile만은 하나의 클래스로 파일에 대한 입력과 출력을 모두 할 수 있도록 되어 있다.

InputStream이나 OutputStream으로 상속받지 않고, DataInput인터페이스와 DataOutput인터페이스를 모두 구현했기 때문에 읽기와 쓰기가 모두 가능하다.

 

DataInputStream은 DataInput인터페이스를, DataOutputStream은 DataOutput인터페이스를 구현했다. 이 두 클래스의 기본 자료형(primitive data type)을 읽고 쓰기위한 메서드들은 모두 이 2개의 인터페이스에 정의되어있는 것들이다.

따라서, RandomAccessFile클래스도 DataInputStream과 DataOutputStream처럼, 기본자료형 단위로 데이터를 읽고 쓸 수 있다. 

RandomAccessFile클래스의 가장 큰 장점은 파일의 어느 위치에나 읽기/쓰기가 가능하다는 것이다.

이것은 RandomAccessFile클래스 내부의 파일포인터를 사용하는데, 입출력 시에 작업이 수행되는 곳이 바로 파일 포이터가 위치한 곳이 된다.

파일 포인터의 위치는 파일의 제일 첫 부분(0부터 시작)이며, 일기 또는 쓰기를 수행할 때 마다 작업이 수행된 다음 위치로 이동하게 된다. 순차적으로 읽기나 쓰기를 한다면, 파일 포인터를 이동시키기 위해 별도의 작업이 필요하지 않지만, 파일의 임의의 위치에 있는 내용에 대해서 작업하고자 한다면, 먼저 파일 포인터를 원하는 위치로 옮긴 다음 작업을 해야 한다.

현재 작업 중인 파일에서 파일 포인터의 위치를 알고 싶을 때는 getFilePointer()를 사용하면 되고, 파일 포인터의 위치를 옮기기 위해서는 seek(long pos)나 skipBytes(int n)를 사용하면 된다.

모든 입출력에 사용되는 클래스들은 입출력 시 다음 작업이 이루어질 위치를 저장하고 있는 포인터를 내부적으로 갖고 있다. 다만 내부적으로만 사용될 수 있기 때문에 작업자가 포인터의 위치를 마음대로 변경할 수 없다는 것이 RandomAccessFile과 다른 점이다.

 

생성자/메서드 설명
RandomAccessFile(File file, String mode)
RandomAccessFile(String fileName, String mode)
주어진 file에 읽기 또는 읽기+쓰기를 하기 위한
RandomAccessFile인스턴스를 생성한다. mode의 값은 "r", "rw", "rws", "rwd"가 지정가능하다.
"r" - 파일로부터 읽기(r)만 수행할 때
"rw" - 파일로부터 읽기(r)와 쓰기(w)를 수행할 때
"rws - rw+출력내용(파일의 내용 + 메타정보)을 파일에 지연없이 바로 쓰이게 한다. 
"rwd"- rw+출력내용(파일의 내용만)을 파일에 지연없이 바로 쓰이게 한다. 
FileChannel getChannel() 파일의 파일 채널을 반환한다.
FileDescriptor getFD() 파일의 파일 디스크립터를 반환한다.
long getFilePointer() 파일의 포인터의 위치를 알려 준다.
long length() 파일의 크기를 얻을 수 있다.(byte단위)
void seek(long pos) 첫 부분부터 pos크기만큼 떨어진 곳까지 파일 포인터의 위치를 변경한다. 
void setLength(long newLength) 파일의 크기를 지정된 길이로 변경한다.(byte단위)
int skipBytes(int n) 지정된 수만큼 byte를 건너뛴다.

RandomAccessFile의 인스턴스를 "rw" mode로 생성할 때, 지정된 파일이 없으면 새로운 파일을 생성한다.

 

public class RandomAccessFileEx1 {
	public static void main(String[] args) {
		try {
			RandomAccessFile raf = new RandomAccessFile("test.dat", "rw");
			System.out.println("파일 포인터의 위치: " + raf.getFilePointer());
			raf.writeInt(100);
			System.out.println("파일 포인터의 위치: " + raf.getFilePointer());
			raf.writeLong(100L);
			System.out.println("파일 포인터의 위치: " + raf.getFilePointer());

		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

파일 포인터의 위치: 0
파일 포인터의 위치: 4
파일 포인터의 위치: 12

이 예제는 파일에 출력작업이 수행되었을 때 파일 포인터의 위치가 어떻게 달라지는지에 대해서 보여 준다.

 

 

 

File

파일은 기본적이면서도 가장 많이 사용되는 입출력 대상이기 때문에 중요하다.

그래서 관련된 기본적인 내용뿐 만 아니라 다양한 활용예제들을 실었다. 이 들을 응용해서 다양한 예제들을 만들어 보면 실력향상에 많은 도움이 될 것이다.

자바에서는 File클래스를 통해서 파일과 디렉토리를 다룰 수 있도록 하고 있다. 그래서 File인스턴스는 파일 일 수도 있고 디렉토리일 수도 있다.

생성자/메서드 설명
File(String fileName) 주어진 문자열(fileName)을 이름으로 갖는 파일을 위한 File인스턴스를 생성한다.파일 뿐만 아니라 디렉토리도 같은 방법으로 다룬다.
여기서 fileName은 주로 경로(path)를 포함해서 지정해주지만, 파일 
File(String pathName, String fileName)
File(File pathName, String fileName)
파일의 경로와 이름을 따로 분리해서 지정할 수 있도록 한 생성자. 이 중 두 번째 것은 경로를 문자열이 아닌 File인스턴스인 경우를 위해서 제공된 것이다.
File(URI uri) 지정된 uri로 파일을 생성
String getName() 파일이름을 String으로 반환
String getPath() 파일의 경로(path)를 String으로 반환
String getAbsolutePath()
File getAbsoluteFile()
파일의 절대경로를 String으로 반환
파일의 절대경로를 File로 반환
String getParent()
File getParentFile()
파일의 조상 디렉토리를 String으로 반환
파일의 조상 디렉토리를 File로 반환
String getCanonicalPath()
File getCanonicalFile()
파일의 정규경로를 String으로 반환
파일의 정규경로를 File로 반환

 

멤버변수 설명
static String pathSeparator OS에서 사용하는 경로(path) 구분자. 윈도우";", 유닉스"."
static char pathSeparatorChar OS에서 사용하는 경로(path) 구분자.
윈도우에서는 ';', 유닉스':'
static String separator OS에서 사용하는 이름 구분자. 윈도우 "\", 유닉스"/"
static char separatorChar OS에서 사용하는 이름 구분자. 윈도우"\", 유닉스"/"

파일의 경로(path)와 디렉토리나 파일의 이름을 구분하는 데 사용 되는 구분자가 OS마다 다를 수 있기 때문에, OS독립적으로 프로그램을 작성하기 위해서는 반드시 위의 멤버변수들을 이용해야한다. 만일 윈도우에서 사용하는 구분자를 코드에 직접 적어 놓았다면, 이 코드는 다른 OS에서는 오류를 일으킬 수 있다.

 

1. 이미 존재하는 파일을 참조할 때 :
File f = new File("c:\\jdk1.8\\work\\ch15", "FileEx1.java");
2. 기존에 없는 파일을 새로 생성할 때 :
File f = new File("c:\\jdk1.8\\work\\ch15", "NewFile.java");
f.creadteNewFile();

 

 

 

메서드 설명
boolean canRead() 읽을 수 있는 파일인지 검사한다.
boolean canWrite() 쓸 수 있는 파일인지 검사한다.
boolean canExecute() 실행할 수 있는 파일인지 검사한다.
int compareTo(File pathname) 주어진 파일 또는 디렉토리를 비교한다. 같으면 0을 반환하며, 다르면 1 또는 -1을 반환한다.(Unix시스템에서는 대소문자를 구별하며, Windows에서는 구별하지 않는다)
boolean exists() 파일이 존재하는지 검사한다.
boolean isAbsolute() 파일 또는 디렉토리가 절대경로명으로 지정되었는지 확인한다.
boolean isDirectory() 디렉토리인지 확인한다.
boolean isFile() 파일인지 확인한다.
boolean isHidden() 파일의 속성이 '숨김(Hidden)'인지 확인한다.
또한 파일이 존재하지 않으면 false를 반환한다.
boolean creadteNewFile() 아무런 내용이 없는 새로운 파일을 생성한다.(단, 생성하려는 파일이 이미 존재하면 생성되지 않는다.)
File f = new File("c:\\jdk1.8\\work\\test3.java");
f.createNewFile();
static File createTempFile
(String prefix, String suffix)
임시파일을 시스템의 임시 디렉토리에 생성한다.
System.out.println(File.createTempFile("work",".tmp"));
결과 : c:\windows\TEMP\work14247.tmp
static File createTempFile
(String prefix, String suffix, File directory)
임시파일을 시스템의 지정된 디렉토리에 생성한다.
boolean delete() 파일을 삭제한다.
void deleteOnExite() 응용 프로그램 종료시 파일을 삭제한다. 주로 실행 시 작업에 사용된 임시파일을 삭제하는데 사용된다.
boolean equals(Object obj) 주어진 객체(주로 File인스턴스)가 같은 파일인지 비교한다. (Unix시스템에서는 대소문자를 구별하며, Windows에서는 구별하지 않는다.)
long lastModified() 파일의 마지막으로 수정된 시간을 지정된 시간으로 반환
long length() 파일의 크기를 반환한다.
String[] list() 디렉토리의 파일목록(디렉토리 포함)을 String배열로 반환한다.
String[] list(FilenameFilter filter)
File[] list(FilenameFilter filter)
FilenameFilter인스턴스에 구현된 조건에 맞는 파일을 String배열(File배열)로 반환한다.
File[] listFiles()
File[] listFiles(FileFilter filter)
File[] listFiles(FilenameFilter f)
디렉토리의 파일목록(디렉토리 포함)을 File배열로 반환(filter가 지정된 경우에는 filter의 조건과 일치하는 파일만 반환)
static File[] listRoots()
long getFreeSpace()
long getTotalSpace()
long getUsableSpace()
컴퓨터 파일시스템의 root의 목록(floppy, CD-ROM, HDD drive)을 반환(예: A:\, D:\)
get으로 시작하는 메서드들은 File이 root일 때, 비어있는 공간, 전체 공간, 사용가능한 공간을 바이트 단위로 반환
boolean mkdir()
boolean mkdrs()
파일에 지정된 경로로 디렉토리(폴더)를 생성, 성공하면 true mkdirs는 필요하면 부모 디렉토리까지 생성
boolean renameTo(File dest) 지정된 파일(dest)로 이름을 변경
boolean setExcutable(boolean excutable)
boolean setExcutable(boolean excutable, boolean ownerOnly)
boolean setReadable(boolean readable)
boolean setReadable(boolean readable, boolean wonerOnly)
boolean setReadOnly()
boolean setWritable(boolean writable)
boolean setWritable(boolean writable, boolean ownerOnly)
파일의 속성을 변경한다.
OwnerOnly가 true면, 파일의 소유자만 해당 속성을 변경할 수 있다.
boolean setLastModified(long t) 파일의 마지막으로 수정된 시간을 지정된 시간(t)로 변경
Path toPath() 파일을 Path로 변환해서 반환
URI toRUI() 파일 URI로 변환해서 반환

 

+ Recent posts