Java의 IO 패키지는 입력(Input)과 출력(Output)을 다루기 위한 다양한 클래스와 인터페이스를 제공합니다.
이 패키지는 java.io 패키지 아래에 위치하며, 데이터를 읽고 쓰는 데 필요한 모든 기능을 포함하고 있습니다. 기본적으로 스트림 기반의 입출력을 지원하며, 스트림은 데이터를 순차적으로 처리합니다.
자바 IO 패키지는 크게 4가지 주요 구분으로 나눌 수 있습니다:
InputStream / OutputStream
바이트 기반의 입력 및 출력 스트림입니다.
파일, 메모리, 프로세스 간 통신 등 다양한 소스로부터 바이트 단위로 데이터를 읽거나 쓸 때 사용됩니다.
예를 들어, FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등이 있습니다.
Reader / Writer
문자 기반의 입력 및 출력 스트림입니다.
텍스트 데이터를 처리할 때 주로 사용되며, 인코딩 문제를 해결하기 위해 설계되었습니다.
FileReader, FileWriter, BufferedReader, BufferedWriter 등이 이에 해당합니다.
RandomAccessFile
파일에 대한 랜덤 액세스(읽기 및 쓰기) 기능을 제공합니다.
파일의 특정 위치를 지정하여 데이터를 읽거나 쓸 수 있습니다.
이 클래스는 java.io 패키지 내에 있지만, InputStream이나 OutputStream의 하위 클래스가 아니라 독립적인 클래스입니다.
파일 및 디렉토리 다루기
파일 시스템의 파일이나 디렉토리를 생성, 삭제, 검사하는 등의 작업을 할 수 있는 클래스를 제공합니다.
File 클래스가 이러한 기능을 담당합니다.
자바 IO 패키지는 블로킹 입출력을 수행합니다. 즉, 어떤 스레드가 입력을 기다리는 동안(또는 데이터를 쓰는 동안) 해당 스레드는 다른 작업을 수행할 수 없습니다. 이러한 특성 때문에 자바 NIO(Non-blocking IO)가 등장했으며, NIO는 IO와는 다르게 채널과 버퍼를 사용하여 논블로킹 입출력 및 선택기(Selector)를 통한 다중 입출력 처리를 지원합니다.
그러나 여전히 많은 자바 애플리케이션들에서는 전통적인 IO 패키지를 사용하여 데이터를 처리합니다. 특히, 파일이나 네트워크 통신 같은 시스템 리소스와의 상호작용을 구현할 때 주로 사용됩니다.
- 입력장치 키보드, File, Network를 사용하는데 InputStream으로 동일하게 입력받기에, 입력받는 방법이 전체적으로 동일하다. (동일한 방법으로 읽어온다)
- 텍스트를 입력받아서, 입력받은 텍스트로 Input을 받아오는 과정
package InputIO;
import java.io.IOException;
import java.io.InputStream;
public class InputIO {
// for ? : 반복횟수를 알 때(length)
// while? : 반복횟수를 모를 때(키보드입력/파일입력)
public static void main(String[] args) throws IOException {
int ch;
InputStream is = System.in; // 미리 입력도구를 만들어놓음(표준입력도구)
System.out.println("데이터를 입력하세요(종료 : Ctrl +Z)");
int count = 0;
while(true) {
ch = is.read(); // 키보드 버퍼로 부터 1Byte 읽어오기
// Ctrl+z 누르면 is.read()메소드가 -1값을 반환한다.
if(ch==-1)break;
System.out.printf("%c", ch);
count++;
}//end-while
System.out.printf("반복횟수 : %d\n",count);
System.out.println("---End---");
}//main-end
}
- 텍스트를 입력받아서, 입력받은 텍스트로 Input을 받아오는 과정
- 위의 과정은 한글이 깨지기 때문에 (한글은 2byte) 1byte로 받아오는 과정을 char의 값으로 변환시켜줘서 한글이 깨지지 않게 값을 받아 출력할 수 있다.
package InputIO;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class InputIO2 {
// for ? : 반복횟수를 알 때(length)
// while? : 반복횟수를 모를 때(키보드입력/파일입력)
public static void main(String[] args) throws IOException {
int ch;
InputStream is = System.in; // 미리 입력도구를 만들어놓음(표준입력도구)
// byte -> char 변환시킬 객체로 filter(byte로 받은 값을 char값으로 재포장 시켜준다)
InputStreamReader isr = new InputStreamReader(is);
System.out.println("데이터를 입력하세요(종료 : Ctrl +Z)");
int count = 0;
while(true) {
ch = isr.read(); // isr로부터 문자 1개
// Ctrl+z 누르면 is.read()메소드가 -1값을 반환한다.
if(ch==-1)break;
System.out.printf("%c", ch);
count++;
}//end-while
System.out.printf("반복횟수 : %d\n",count);
System.out.println("---End---");
}//main-end
}
키보드 -> 키보드버퍼(임시저장소) -> 모니터(콘솔)
▶Quece(큐) : FIFO(First in First Out) (선입선출)
▶Stack(스택) : LIFO(Last in First Out) (후입선출)
키보드버퍼(임시저장소)의 데이터 처리는 큐처리로 선입선출 방식이다.
- 텍스트 파일을 만들어서, 파일로 Input을 받아오는 과정
package InputIO;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
// 파일로부터 출력 받기
public class _02_FileInput {
public static void main(String[] args) throws IOException, InterruptedException {
// 이 파일이 없으면 어떻게 처리할래? 라고 물어본다. 예외처리 해주면 감사.
InputStream is = new FileInputStream("a.txt"); // 업캐스팅
int ch;
while(true) {
ch = is.read();
// File 끝이면 종료 (text 파일의 끝이 -1로 나타나기 때문에, 자동으로 종료된다)
if(ch==-1) break;
System.out.printf("%c", ch);
Thread.sleep(500);
}
// 파일 열어놨는데 못닫으면 어떻게 할래? 예외처리 해주면 감사. main에게 이관시키는게 주특기
is.close();
System.out.println("---End---");
}//main-end
}
▶텍스트로부터 받았거나, 파일로부터 받았거나 입력방식이 똑같다.
- 네트워크를 읽어서, 네트워크를 Input을 받아오는 과정
package InputIO;
import java.io.InputStream;
import java.net.URL;
public class _03_NetworkInput {
public static void main(String[] args) throws Exception {
String str_url = "https://www.naver.com/";
// 예외가 뜨는 것은 너 이 주소 없으면 어떡할래!! 라고 물어보는 것임 main에게 넘기는게 주특기
URL url = new URL(str_url);
// 이 웹서버에 연결된 주소를 인풋으로 넣겠다.
InputStream is = url.openStream();
int ch;
int count = 0;
while(true) {
ch = is.read();
// 네이버에 올라와있는것도 문서형태이다. 끝은 결국 -1값이 나온다.
if(ch==-1)break;
System.out.printf("%c", ch);
count++;
}//while-end
System.out.printf("반복횟수 : %d\n",count);
System.out.println("---End---");
}//main-end
}
- 네트워크를 읽어서, 네트워크를 Input을 받아오는 과정
- 위 버전은 글씨가 깨지기 때문에, char로 변환하여 받아준다.
package InputIO;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class _03_NetworkInput2 {
public static void main(String[] args) throws Exception {
String str_url = "https://www.naver.com/";
// 예외가 뜨는 것은 너 이 주소 없으면 어떡할래!! 라고 물어보는 것임 main에게 넘기는게 주특기
URL url = new URL(str_url);
// 이 웹서버에 연결된 주소를 인풋으로 넣겠다.
InputStream is = url.openStream();
InputStreamReader isr = new InputStreamReader(is);
int ch;
while(true) {
ch = isr.read();
// 네이버에 올라와있는것도 문서형태이다. 끝은 결국 -1값이 나온다.
if(ch==-1)break;
System.out.printf("%c", ch);
}//while-end
System.out.println("---End---");
}//main-end
}
- CharSet을 euc-kr로 준다면, 네트워크에서 가져온 문서는 UTF-8 방식으로 인코딩 되기 때문에, 글씨가 깨져서 출력하게 된다.
(ASCII 'A' -> 65, 만약 '가'라는게 euc-kr에서는 100이라면, UTF-8에서 '가'는 1000을 받는다면, euc-kr에서 UTF-8에서의 '가'를 받아주면 100으로 받아야 할 '가'를 1000으로 받기에 이상한 문자가 출력되는 것이다)
- 위에는 전부 char로 받아서 한 글자씩 받아오기 때문에 업로드 속도가 느리다.
- 그렇기 때문에, BufferedReader를 사용하면, 버퍼에 데이터를 전부 가져와서, enter로 구분되어 있는 라인을 하나씩 가져오게 되는데, 그 라인 자체를 하나씩 불러오기에, 시간이 정말 단축이 많이 된다.
package InputIO;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
public class _03_NetworkInput3 {
public static void main(String[] args) throws Exception {
String str_url = "https://www.naver.com/";
// 예외가 뜨는 것은 너 이 주소 없으면 어떡할래!! 라고 물어보는 것임 main에게 넘기는게 주특기
URL url = new URL(str_url);
// 1차적으로 읽는다.
InputStream is = url.openStream();
// 2차적으로 읽는다.
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
// 성능향상, 3차적으로 읽는다.
BufferedReader br = new BufferedReader(isr);
String data;
int line_count = 0;
// int ch;
while(true) {
data = br.readLine(); // Enter까지 읽어온다-> 엔터제외하고 넘긴다.
if(data==null) break;
System.out.println(data);
line_count++;
}//while-end
System.out.printf("라인의 갯수 : %d\n", line_count);
}//main-end
}
- 반복된 횟수는 14번으로 한 번씩 가져올 때 라인 한 줄을 전체적으로 가져오는 것을 알 수 있다.
▶OutputStream 활용해서 출력하기
package output;
import java.io.IOException;
import java.io.OutputStream;
public class _01_MonitorOutput {
public static void main(String[] args) throws IOException {
// 입력표준 : System.in
// 출력표준 : System.out
OutputStream os = System.out; // System.out으로 부르는건 System 클래스의 static 변수 호출이다.
// 문자
char ch = 'A';
os.write(ch); // 출력버퍼에 기록
os.write(66); // 출력버퍼에 기록
os.flush(); // 출력버퍼를 비워라 -> 모니터로 전송
// 문자열
String msg = "안녕하세요";
// String -> byte []
byte [] msg_bytes = msg.getBytes();
os.write(msg_bytes);
// 정수 (String으로 받아서 int로 변환
int age = 20; // '0' : 48
// 모든값을 문자열 변환 : String.valueOf(값)
os.write(String.valueOf(age).getBytes());
// 실수
double boy_length = 180.5;
os.write(String.valueOf(boy_length).getBytes());
boolean bOk = "파리".equals("새");
os.write(String.valueOf(bOk).getBytes());
}//main-end
}
package output;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
public class _02_FileOutput {
public static void main(String[] args) throws Exception {
OutputStream os = new FileOutputStream("b.txt");
// 문자
char ch = 'A';
os.write(ch);
// 문자열 출력
String msg = "아울렛에서 가서 쇼핑을 해봅시다.";
os.write(msg.getBytes());
// 앤터
os.write('\n');
os.write('\n');
// 숫자
os.write(String.valueOf(30).getBytes());
os.write('\n');
os.write(String.valueOf(123.56).getBytes());
// 편리하게 사용하기 위해서 filltering
// 자, 이제부터 내가 format 형식을 정해서 마음껏 출력이 가능하다!
PrintStream out = new PrintStream(os);
out.println("\n---지금부터는 PrintStream을 이용---");
String name = "홍길동";
int age = 31;
String tel = "010-4040-4040";
boolean bMarried = true;
out.printf("이름 : %s\n", name);
out.printf("나이 : %d(살)\n", age);
out.printf("전화번호 : %s\n", tel);
out.printf("결혼유무 : %s\n", bMarried ? "기혼" : "미혼");
os.close(); // 파일은 사용했으면 닫아야 한다. 닫아야 다른 사람도 자원을 사용이 가능하다.
}//main-end
}
-직렬화 : 넘겨줄 때 쭈우우욱 넘겨줍니다. oos.writeObject(p1);
-역직렬화 : 넘어올 때 순서대로 읽어와서 해당타입에 맞는 객체로 조립 레고 조립 (객체명)ois.readObject();
-직렬화를 가능하게 해주려면 implements Serializable을 넣어주어야 한다.
-Serializable을 들어가면 인터페이스에 딱히 기능이 없는데, 그냥 식별해주는 표시로 생각하면 된다.
package vo;
import java.io.Serializable;
// PersonVo가 직렬화 가능한 객체로 표현 : Serializable
public class PersonVo implements Serializable{
// alt + shift + s
// Vo의 구조가 완벽하게 들어맞아야, 역직렬화 할 때 오류가 나지 않는다.
String name;
int age;
String addr;
public PersonVo() {
// TODO Auto-generated constructor stub
}
public PersonVo(String name, int age, String addr) {
super();
this.name = name;
this.age = age;
this.addr = addr;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return String.format("[%s-%d-%s]", name, age, addr);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
package serial;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import vo.PersonVo;
public class _01_Serial_Person {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
PersonVo p = new PersonVo("차선일", 31, "서울특별시 양천구 목5동");
// 직렬화로 저장된 파일 : binary 파일 (2진법)
OutputStream os = new FileOutputStream("person.dat");
// 객체를 저장할 수 있는 Filter 객체 생성
ObjectOutputStream oos = new ObjectOutputStream(os);
// 저장
oos.writeObject(p);
// 열린역순으로 닫기 (항상 파일이 열려있으면 닫아줘야 한다. 다른이들이 열어볼 수 있게)
oos.close();
os.close();
}//main-end
}
- ArrayList
- Map
package note;
import java.util.Scanner;
public class Note {
public void run() {
while(true) {
Scanner scanner = new Scanner(System.in);
System.out.println("안녕하세요, 차선일의 메모하고 싶은 날 입니다.");
System.out.println("1. 메모리스트 2. 메모보기 3. 메모작성 4. 메모수정 5. 메모삭제 6. 종료");
System.out.println("번호를 입력해주세요.");
int selectedNumber = scanner.nextInt();
if(1 == selectedNumber) {
} // 메모 전체보기 처리
else if (2 == selectedNumber) {
} // 메모 상세보기 처리
else if (3 == selectedNumber) {
} // 메모 추가하기 처리
else if (4 == selectedNumber) {
} // 메모 수정하기 처리
else if (5 == selectedNumber) {
} // 메모 삭제하기 처리
else if (6 == selectedNumber) {
break;
} else {
System.out.println("번호를 다시입력해주세요");
}
}// while-end
}// run-edn
}
- transient를 변수에 넣어주면 직렬화에서 제외가 된다.
# File 클래스
※ 자바 프로그램 안에서 File을 관리하는 기능
- 파일 시스템의 파일을 표현하는 클래스
- 파일 크기, 파일 속성, 파일 이름 등의 정보 제공
- 파일 생성 및 삭제 기능 제공
- 디렉토리 생성, 디렉토리에 존재하는 파일 리스트 얻어내는 기능 제공
# 파일 객체 생성
- 파일 및 디렉토리의 정보를 리턴하는 메서드
File f = new File("d:\\dev"); // 제어문자 :\n \r \t \를 문자로 인식 : \\ 두개로 사용
// "\"" : ""안에 "를 넣고 싶으면 앞에 \를 사용
// Directory 생성
File ff = new File(f,"myfolder");
// 존재하지 않으면 생성해라
if(ff.exists()==false) // ff.exists : 존재하면 true가 출력된다.
ff.mkdir();
// 삭제
ff.delete();
System.out.println("---[파일목록]----");
for(int i = 0; i<f_array.length;i++) {
File f_local = f_array[i];
// StringBuffer vs StringBuilder
// 속도 O
// 쓰레드동기화 O X
StringBuilder sb = new StringBuilder("[");
// String kind = "[";
if(f_local.isDirectory())
sb.append("D");
if(f_local.isFile())
sb.append("F");
// 얘는 else 걸면 안된다.
if(f_local.isHidden())
sb.append("H");
sb.append("]");
String name = f_local.getName();
long len = f_local.length();
if(f_local.isFile())
System.out.printf("[%d] : %s %s (%d bytes)\n",i , sb.toString(), name, len);
else if(f_local.isDirectory())
System.out.printf("[%d] : %s %s\n",i , sb.toString(), name);
}
'java(2)↗' 카테고리의 다른 글
VO와 DTO와 DAO (0) | 2024.05.12 |
---|---|
java 네트워크 (0) | 2024.05.10 |
java 이클립스 템플릿 Template (0) | 2024.05.08 |
java 람다식(+다형성 추가 설명) (0) | 2024.05.08 |
java 요약노트 (0) | 2024.05.08 |