본문 바로가기

Java

18일차 공부 IO, Serializable

1 교시

 

** Input & Output(IO)

=> Main Memory와 주변 장치 (파이르키보드나 미노터와 같은 입출력 장치, 네트워크 등) 들간의 통신

1. java.io.File 클래스

=> 파일에 대한 정보를 리턴해주는 클래스

1) 경로(위치) 설정

=> 절대 경로 : 루트로부터의 경로, 불변의 경로

윈도우즈 : c:\디렉토리이름\파일명

그외의 운영체제 : /디렉토리이름.../파일명

웹 : http://요청경로

 

윈도우즈만 디렉토리 구분기호가 \이고 나머지 경우는 전부 /

윈도우즈의 경로를 표시할 때는 \\로 표현해야 한다.

 

=> 상대 경로 : 현재 위치로부터의 경로, 현재 위치에 따라 변함

./ : 현재디렉토리

../ : 상위 디렉토리

 

현재 디렉토리는 생략해도 되는 경우가 대부분이고 Mac의 경우는 터미널에서 에러가 난다.

 

2) 파일 객체 생성

 

File(String pathname)

File(String parent, String child)

=> 파일의 경로를 가지고 생성

 

3) 중요한 메소드

boolean exist() : 파일의 존재 여부를 리턴

boolean delete() : 파일을 삭제하고 삭제 성공 여부를 리턴

lont lastModified() : 최후 수정 시간을 정수로 리턴

long length() : 파일의 크기를 리턴

String[] list(): 디렉토리의 경우 내부에 존재하는 파일의 목록을 문자열로 리턴

 

4) 서버로부터 데이터를 다운로드 받는 애플리케이션을 생성

=> 서버에 접속할 때 마다 데이터를 다룬로드 받는 것은 자원의 낭비

=> 처음에 접속할 때 데이터를 다운로드 받아서 파일로 저장해두고 사용

=> 다음에 접속했을 때는 데이터의 변경이 발생했으면 다운로드하고 그렇지 않으면 이전에 저장한 데이터를 계속 사용 

 

 

 

 

2. java.nio.file.Path

=> File 클래스에 기능을 추가한 새로 등장한 API

=> FIle 클래스는 symbolic link(바로가기)를 생성할 수 없다. 

=> File 클래스는 디텍토리 밑의 파일의 생성/생식/삭제를 갑시할 수 없다.

 

3. 입출력 Stream

=> 데이터를 주고받는 연결 통로

=> 파일이나 네트워크 등과 통신하기 위해서는 스트림이 필요

1) 입출력에 따른 분류

=> Input Stream : 입력을 받기 위한 스트림 - 외부에서 읽어오기 위한 스트림

=> Output Stream : 출력을 하기 위한 스트림 - 내부의 데이터를 전송하기 위한 스트림

 

2) 전송 단위에 따른 분류

=> Byte Stream : 바이트 단위로 전송하는 스트림, 그림 파일 처럼 문자가 아닌 데이터의 전송에 사용, 이 기종 간의 통신에 이용

=> Character Stream : 문자 단위 전송

=> Object Stream : 인스턴스로 단위로 전송

=> 자바 소켓 서버와 iOS가 채팅을 하는 경우 기본적으로는 ByteStream을 이용한다.

 

 

 

2 교시

 

** Byte Stream

=> 데이터를 Byte 단위로 주고 받는 스트림

1. InputStream & OutputStream

1) InputStream

=> Byte 단위로 입력받기 위한 스트림을 위한 추상 클래스

=> 공통으로 사용할 메소드를 선언한 클래스

 

int available() : 읽을 수 있는 바이트 수 리턴

void close() : 스트림 닫는 메소드

 

int read() : 하나의 바이트를 읽어서 정수로 리턴, 읽은 데이터가 없으면 -1을 리턴

int read(byte [] b) : 데이터를 읽어서 b에 저장하고 읽은 바이트 수를 리턴, 읽은 데이터가 없으면 -1을 리턴

int read(byte [] b, int off, int len) : 데이터를 읽어서 b에 저장하는데 off부터 len만큼만 저장하고 읽은 바이트 수를 리턴, 읽은 데이터가 없으면 -1을 리턴

 

long skip(long n) : n 만큼 넘어가는 메소드

 

2. OutputStream

=> 바이트 단위로 데이터를 전송하기 위한 스트림의 추상 클래스

=> 다른 클래스에서 공통으로 사용할 메소드를 선언만 한 클래스

 

void close() : 스트림을 닫는 메소드

void write(int b) : b 1개를 전송

void write(byte [] b) : b 배열을 전송

void write(byte [] b, int off, int len) : b 배열에서 off 부터 len 만큼 전송

 

void flush() : 버퍼의 내용을 전부 전송

 

> 데이터를 전송할 때는 버퍼에 모아서 한꺼번에 전송한다.

write로 데이터를 전송할 때 버퍼의 크기를 넘어서면 전송을 하지만 그렇지않으면 전송하지 않는 경우가 발생하는데 이 때는 flush를 이용해서 내용을 전부 전송해 주어야 한다.

 

3. FileInputStream & FileOutputStream

=> 파일에 바이트 단위로 기록하고 읽어오는 클래스

=> 파일 경로를 생성자에 입력해서 인스턴스를 생성

=> 생성할 때 파일의 경로가 없을 수 있어서 FileNotFoundException 예외처리를 해야한다.

=> 기록을 하는 클래스의 생성자는 읽기를 하는 클래스의 생성자보다 1개 정도가 더 많다.

기록을 할 때는 전부 지우고 기록할 것인지 아니면 이어서 쓸 것인지를 설정해주어야 하기 때문이다.

기본은 전부 지우고 기록을 하는 것이다.

 

코드를 실행할 때마다 "안녕하세요"가 추가로 작성된다.

안녕하세요안녕하세요안녕하세요

 

 

 

파일의 내용을 바이트 단위로 읽고 쓰는 방법

 

 

 

 

3 교시

 

4. BufferedInputStream & PrintStream

=> 버퍼를 이용해서 입출력 효율을 높이기 위한 스트림

=> 버퍼를 이용하지 않으면 입출력 메소드를 호출할 때 마다 운영체제의 native mtehod를 호출해서 효율이 나빠질 수 있다.

=> 버퍼에 모아서 한꺼번에 처리하는 방식을 권장

=> 인스턴스를 생성할 때 다른 스트림 인스턴스를 받아서 생성한다.

 

** Character Stream

=> 문자 단위로 데이터를 주고 받는 스트림

=> 파일 전송 등에는 사용할 수 없고 오로지 문자 전송에만 사용하는 스트림

 

1. Reader

=> 문자 단위 읽기에 사용하는 메소드를 소유한 추상 클래스

void close()

int read()

int read(char [] buf)

int read(char [] buf, int off, int len)

 

long skip(long n)

 

2. Writer

=> 문자 단위 쓰기에 사용되는 메소드를 소유한 추상 클래스

void close()

void write(String str)

void write(String str, int off, int len)

void flush()

 

 

 

4 교시

 

3. FileReader & FileWriter

=> 파일에 문자 단위로 읽고 쓰기 위한 스트림

=> 이 클래스의 인스턴스를 이용해서 읽고 쓰기를 하면 Navive Method를 자주 호출해서 입출력의 효율이 떨어질 수 있다.

 

4. BufferedReader & PrintWrite

1) BufferedReader

=> 버퍼를 이용해서 문자 단위로 읽고 쓰는 클래스

String readLine() 

 

String readLine메소드가 추가되어 있다. 

한 줄의 문자열을 읽어서 문자열로 리턴하는 메소드로 읽은 데이터가 없으면 null을 리턴(암기)

 

2) PrintWriter

=> 버퍼를 이용해서 문자 단위로 쓰는 클래스

=> print 와 println 메소드가 있다.

 

CharacterBufferedWriter

 

CharacterBufferedReader

 

 

 

 

 

5 교시

 

** 데이터 표현

1) 하나의 값 - Scala Data

boolean, bytem short, int, long, float, double

 

String, Date(날짜) : 분할이 가능한 데이터

 

2) 하나의 행을 위한 자료형

Map

별도의 클래스를 만들고 인스턴스를 생성

 

3) 하나의 열을 위한 자료형

Array(배열)

ArrayList

LinkedList

 

4) 테이블 구조

Map의 Array, ArrayList, LinkedList

별도의 클래스의 Array, ArrayList, LinkedList

 

** Serializable(직렬화)

=> 데이터를 전송(파일 입출력, 네트워크 입출력)할 때 인스턴스 단위로 전송할 수 있도록 해주는 것 또는 인터페이스

=> 데이터는 하나로 묶어서 읽고 쓰기를 해야 하는데 이전까지의 스트림은 바이트나 문자단위로만 작업

 

1. ObjectInputStream & ObjectOutputStream

=> Serializable 인터페이스를 implements 한 인스턴스를 입출력하기 위한 스트림

1) ObjectInputStream

=> 인스턴스 단위로 읽어오기 위한 클래스

=> 생성자

ObjectInputStream() : 매개변수 없는 생성자

ObjectInputStream(InputStream inputStream : 다른 InputStream을 매개변수로 받아서 생성

 

new ObjectInputStream(new FileInputStream(파일경로))

=> 파일 경로

new File("파일 경로")

"파일 경로"

 

=> 주요 메소드

void close() : 스트림 닫는 메소드

스트림은 열면 반드시 받아야 한다.

 

Object readObject() : 인스턴스1개를 읽어서 Object타입으로 리턴

사용할 때는 원래의 자료형으로 강제형변환해서 사용해야 한다.

데이터는 묶어서 1개로 표현해야 된다.

 

2) ObjectOutputStream

=> 인스턴스 단위로 기록하기 위한 스트림

=> 생성자

ObjectOutputStream()

ObjectOutputStream(OutputStream) : 다른 OutpuStream 인스턴스를 가지고 생성

 

new ObjectOutputStream(new FilePutputTream(파일 경로, boolean append)

 

2. Serializable 인터페이스

=> 자바에서 인스턴스 단위로 입출력할 수 있도록 해주는 인터페이스

=> implements 하면 그걸로 끝 - 메소드를 구현할 필요가 없음

=> 안드로이드에서 Activity 사이의 데이터 전송에도 이 인터페이스가 이용

package javaapp0501;

import java.io.Serializable;

// 영화코드(문자열), 영화제목(문자열), 영화평(실수)을 저장하는 클래스 
public class DTO implements Serializable {
private String code;
private String title;
private double grade;
public DTO() {
super();
}
public DTO(String code, String title, double grade) {
super();
this.code = code;
this.title = title;
this.grade = grade;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
@Override
public String toString() {
return "DTO [code=" + code + ", title=" + title + ", grade=" + grade + "]";
}

}
package javaapp0501;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableMain {

public static void main(String[] args) {
// 파일에 인스턴스 단위로 기록
try (ObjectOutputStream oos = 
new ObjectOutputStream(
new FileOutputStream("./oo.dat"))) {
// DTO 클래스의 인스턴스를 생성
DTO dto = new DTO("a01", "Matrix", 5.0);
// 파일에 기록
oos.writeObject(dto);
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

try (ObjectInputStream ois = 
new ObjectInputStream(
new FileInputStream("./oo.dat"))) {
// DTO 클래스의 인스턴스를 생성
DTO dto = (DTO)ois.readObject();
System.out.println(dto);
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

}

}

 

 

 

split, substring 문자열을 특정단위로 나눌때 사용

 

여러개를 묶을 때는 list가 좋다. class, map, list(동일한애)

 

 

 

6 교시

package javaapp0501;

import java.io.Serializable;

// 영화코드(문자열), 영화제목(문자열), 영화평(실수)을 저장하는 클래스 
public class DTO implements Serializable {
private String code;
private String title;
private double grade;
public DTO() {
super();
}
public DTO(String code, String title, double grade) {
super();
this.code = code;
this.title = title;
this.grade = grade;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
@Override
public String toString() {
return "DTO [code=" + code + ", title=" + title + ", grade=" + grade + "]";
}


}
package javaapp0501;

import java.io.Serializable;

// 영화정보를 저장할 클래스 - VO, DTO, Domain 클래스라고도 한다.
public class MovieDTO implements Serializable{
// 데이터를 구성할 프로퍼티를 private으로 선언
// 번호(정수), 영화제목(문자열), 영화감독(문자열), 주연배우(문자열)
private int num;
private String title;
private String director;
private String actor;

// 이번 작업은 대두분 데이터베이스를 사용하기 전에만 수행
// 인스턴스를 빠르게 만들기 위한 생성자 추가
public MovieDTO() {
super();
}
public MovieDTO(int num, String title, String director, String actor) {
super();
this.num = num;
this.title = title;
this.director = director;
this.actor = actor;
}
// 접근자 매소드 - getter & setter
// 프로퍼티를 private으로 만들었기 때문에
// 인스턴스가 직접 접근이 안되서 프로퍼티에 접근하기 위해서 만든 메소드
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}

// 디버깅을 위한 메소드
// 이 메소드를 만들지 않으면 인스턴스 이름을 가지고 인스턴스를 출력할 때 클래스 이름과 해시코드가 리턴
// 프로퍼티의 값을 빠르게 확인하기 위해서 만드는 메소드
@Override
public String toString() {
return "MovieDTO [num=" + num + ", title=" + title + ", director=" + director + ", actor=" + actor + "]";
}

}
package javaapp0501;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class MovieDTOMain {

public static void main(String[] args) {
// MovieDTO 클래스의 인트턴스 2개 만들기
MovieDTO obj1 = new MovieDTO(1, "기생충", "봉준호", "최우식");
MovieDTO obj2 = new MovieDTO();
obj2.setNum(2);
obj2.setTitle("Matrix");
obj2.setDirector("Wachowski");
obj2.setActor("Keanu Reeves");

// 위의 2개를 배열로 묶기
MovieDTO [] ar = {obj1, obj2};

// ArrayList로 묶기
ArrayList list = new ArrayList<>();
list.add(obj1);
list.add(obj2);

// 오늘 날짜를 문자열로 만들기
Date date = new Date();
// 날짜를 원하는 포맷의 문자열로 만들어주는 인스턴스
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String today = sdf.format(date);
//System.out.println(today);

// 파일에 기록
// OvhectOutputStream
// FileOutputStream 인스턴스를 이용해서 생성
// 파일의 경로를 가지고 생성
try (ObjectOutputStream oos = 
new ObjectOutputStream(
new FileOutputStream(today + ".dat"))){
// 파일에 기록
oos.writeObject(list);
}catch(Exception e) {

}

}

}
package javaapp0501;

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;

public class MovieDTORead {

public static void main(String[] args) {
// 인스턴스 단위로 기록한 파일 읽기
try(ObjectInputStream ois = 
new ObjectInputStream(
new FileInputStream("2020-05-01.dat"))) {
ArrayList list = (ArrayList)ois.readObject();
for(MovieDTO dto : list) {
System.out.println(dto);
}

}catch(Exception e) {
System.out.println(e.getMessage());
}

}

}
package javaapp0501;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializableMain {

public static void main(String[] args) {
// 파일에 인스턴스 단위로 기록
try (ObjectOutputStream oos = 
new ObjectOutputStream(
new FileOutputStream("./oo.dat"))) {
// DTO 클래스의 인스턴스를 생성
DTO dto = new DTO("a01", "Matrix", 5.0);
// 파일에 기록
oos.writeObject(dto);
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

try (ObjectInputStream ois = 
new ObjectInputStream(
new FileInputStream("./oo.dat"))) {
// DTO 클래스의 인스턴스를 생성
DTO dto = (DTO)ois.readObject();
System.out.println(dto);
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

}

}
DTO [code=a01, title=Matrix, grade=5.0]

 

 

7~8 교시

 

** String의 주요 메소드

int length() : 문자열의 길이를 리턴

char charAt(int idx) : idx 번째에 해당하는문자 리턴

 

String toUpperCase() : 대문자로 리턴

String toLowerCase() : 소문자로 리턴

 

String split(String 구분문자열) : 구분문자열을 가지고 분할해서 String 배열로 리턴

 

String substring(int start) : start부터 end앞까지 문자열을 분할해서 리턴

 

int indexOf(String str) : str을 앞에서부터 찾아서 가장 먼저 찾은 인덱스를 리턴

int lastIndexOf(String str) : str을 앞에서부터 찾아서 가장 나중에 찾은 인덱스를 리턴

String trim() : 좌우 공백을 제거해서 리턴

 

byte getBytes() : 바이트 배열을 리턴

 

** 문자열을 숫자로 만들기

Integer.parseInt(String str)

Double.parseDouble(String str)

 

** 텍스트 파일을 읽어내는 스트림

BufferedReader(new InputStreamReader(new FileInputStream(String 파일경로)))

 

줄단위로 읽어서 문자열로 리턴하는 메소드 : String readLine()

읽은 데이터가 없으면 null

 

1. log.txt 파일에서 서버에 접속한 IP를 중복없이 출력

C:\Users\30405\eclipse-workspace\javaapp0501\log.txt

 

 

 

 

2. log.txt. 파일에서 서버에 접속해서 사용한 traffic(줄에서 열번째 데이터) 의 합계를 출력

 

3. log.txt 파일에서 서버에서 접속해서 사용한 traffic의 합계를 ip 별로 출력

=> HashMap을 이용해서 구현