본문 바로가기
JAVA

JAVA 11일차

by teg0 2025. 8. 20.

파일 입출력

간단하게 파일 폴더 생성하고 정보확인

java.io.File 클래스를 이용

파일/폴더 경로를 표현하는 객체

 

상대경로 : 지금 내 위치를 기반으로 다른 경로를 탐색

절대경로 : 윈도우 기준으로 C:~ D:~, Unix기준으로 /root/~ 최상위 루트를 기준을 다른 경로를 탐색

 

public static void main(String[] args) {
		
    //1. 경로지정없이 파일객체를 생성(상대경로 - 현재 작업 폴더 기준)
    File f1 = new File("test.txt"); 
            //파일 객체를 하나 생성(실제파일X -> 코드로 존재하는 파일 객체)

    //2. 실제 존재하는 경로에 파일 생성(절대경로)
    File f2 = new File("D:\\test.txt");

    //3. 존재하지 않는 경로에 파일 생성
    File f3 = new File("D:\\tmp\\test.txt");

    try {
        f1.createNewFile(); //createNewFile() 시점에 실제 파일이 만들어 짐.
        f2.createNewFile();
      //f3.createNewFile(); 존재하지 않는 경로로 생성시 예외발생 -> IOException

        //폴더를 먼저 생성하고 파일을 만들면 됨
        File tmpFolder = new File("D:\\\\tmp");
        tmpFolder.mkdir();
        f3.createNewFile();

        //파일정보 가져오기
        File f4 = new File("ttt.txt");

        //exists() 파일 존재 유무 확인
        System.out.println("exists : "+ f4.exists());
        System.out.println("exists : "+ f1.exists());

        //isFile() 파일 유무 확인
        System.out.println("isFile : " + f1.isFile());
        System.out.println("isFile : " + tmpFolder.isFile());

        System.out.println("파일명 : " + f1.getName());
        System.out.println("파일경로 : " + f1.getAbsolutePath());
        System.out.println("파일용량 : " + f1.length());
        System.out.println("파일상위폴더 : " + f1.getParent());


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

 


자바 스트림

프로그램가 외부매체(파일, 네트워크, 콘솔...) 간의 데이터 전달 통로

데이터를 순차적으로 흘려보내는 파이프같은 구조

 

스트림의 특징

  1. 단방향 : 입력이면 입력만, 출력이면 출력만 가능 -> 동시에 원하면 각각 만들어줘야한다.
  2. 순차적으로 처리(FIFO) : 먼저 보낸 데이터가 먼저 나온다.
  3. 시간 지연 가능성 : 외부매체와 연결되므로 입출력속도가 상대적으로 느릴 수 있음.

스트림의 구분

데이터 단위에 따른 구분(바이트스트림(1Byte), 문자스트림(2Byte))

  • 바이트스트림(InputStream, OutputStream) : 이미지, 동영상, 바이너리 데이터 등...
  • 문자스트림(Reader, Writer) : 텍스트 데이터(문자/문자열)...

외부 매체 연결 방식에 따른 구분

  • 기반스트림 : 외부 매체와 직접연결되는 스트림(필수, 단독 사용가능)
  • 보조스트림 : 기반스트림 감싸서 성능 향상이나 기능추가 제공(단독사용불가, 반드시 기반스트림과 함께 사용)

프로그램에서 파일(출력) 

public void fileSave() {
    try (BufferedWriter bw = new BufferedWriter(new FileWriter("1_buffer.txt"));){


        /*
        //1. 기반스트림 생성
        FileWriter fw = new FileWriter("1_buffer.txt");

        //2. 보조스트림 생성시 기반스트림 객체를 전달하여 새성
        BufferedWriter bw = new BufferedWriter(fw);

        fw.close();
        */ //-> 위에 작성한 try()와 주석처리는 같다.

        bw.write("안녕하세요");
        bw.write("안녕하세요");
        bw.newLine();
        bw.write("안녕하세요");
        bw.flush(); //버퍼 강제 비움

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

 1_buffer.txt가 없으면 파일을 만들고 있으면 만들지 않는다.

bw객체로 write메서드를 사용하여 파일에 작성하고 

flush로 남은 데이터들을 비운다.

 

public void fileSaveWithStream() {
    FileOutputStream fo = null;

    try{
        //1. 기반스트림 생성
        fo = new FileOutputStream("1_buffer.txt");

        //2. 기반 스트림 -> OutputStream을 writer로 사용할 수 있게 보조
        OutputStreamWriter osw = new OutputStreamWriter(fo, "UTF-8");

        //3. 보조스트림 생성시 기반스트림 객체를 전달하여 생성
        BufferedWriter bw = new BufferedWriter(osw);

        bw.write("안녕하세요\n");
        bw.write("안녕하세요");
        bw.newLine();
        bw.write("안녕하세요");
        bw.flush(); //버퍼 강제 비움

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fo.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

외부매체(파일) -> 프로그램(입력)

public void fileRead() {
    try (BufferedReader br = new BufferedReader(new FileReader("1_buffer.txt"));){
        /*
        System.out.println(br.readLine());
        System.out.println(br.readLine()); 파일에 모든 내용을 읽은 후에는 null반환
        */
        String text = null;
        while((text = br.readLine()) != null) {
            System.out.println(text);
        }

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

FileReader : 파일을 직접적으로 연결해서 2바이트 단위로 입력받을 수 있는 기반스트림
BufferedReader : 한줄씩 읽어오는 기능이 가능한 보조스트림


직열화와 역직열화

직열화

객체는 메모리안에서 존재하는 인스턴스 개념이기 때문에 그대로 전송할 수 없음, 직열화 후 이진데이터로 외부에 전송 가능.

객체(object)를 바이트 형태로 변환하는 과정

파일에 저장하거나 네트워크로 전송할 수 있도록 함

자바에서는 클래스를 직열화하기위해 직열화 대상 클래스에게는 implements Serializable 해야한다.

 

역직열화

저장해 두거나 전송했던 데이터를 다시 원래 객체처럼 사용하기 위해 역직렬화 진행

저장된 바이트 데이터를 다시 객체로 복원하는 과정

 

프로그램 -> 파일(출력) : 객체(직열화)

public void objectSave() {
    Product p1 = new Product("아이폰16", 1200000);
    Product p2 = new Product("아이폰16pro", 1400000);
    Product p3 = new Product("아이폰16mini", 1000000);

    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("product1.dat"));){
        oos.writeObject(p1); //직렬화 후 파일에 객체를 저장
        oos.writeObject(p2);
        oos.writeObject(p3);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

열어보면 저장되어 있지만, 사람이 읽을 수 없는 문자들이 저장되어 있다.

 

파일 -> 프로그램(입력) : 객체바이트코드(역직렬화)

public void objectRead() {
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("product1.dat"));){
        Object obj = ois.readObject();
        if (obj instanceof Product) {
            Product p1 = (Product)obj; //Object이기에 다운캐스팅
            System.out.println(p1);
        }

    } catch (IOException e) {
        System.out.println("객체 읽기 중 에러 발생");
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        System.out.println("직렬화 대상을 찾을 수 없습니다.");
        e.printStackTrace();
    }
	}

 

public class Product implements Serializable{
	private String name;
	private int price;

	public Product() {
		super();
	}

	public Product(String name, int price) {
		super();
		this.name = name;
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Product [name=" + name + ", price=" + price + "]";
	}
	
}

JAVA  API

API는 프로그램을 만들 때 사용할 수 있도록 제공되는 미리 만들어진 기능의 모음.

-> 미리 작성해 둔 유용한 인터페이스(명령어, 클래스, 메서드, 라이브러리 등)

 

자바 API(자바 표준 라이브러리)

자바언어는 기본 문법(변수, 제어문, 클래스 등...)만 제공

실제 개발할 때는 문자열 처리, 날짜 계산, 입출력, 네트워크 통신, 자료구조 상용 등 수많은 기능이 필요

이런 기능을 자바 개발팀에서 미리 구현해 둔 클래스/인터페이스 집합을 JAVA 표준 API

ex) java.lang.String, java.io.File 등...

 

String

public void method01() {
    //1. 생성자를 통한 문자열 생성
    String str1 = new String("Hello");
    String str2 = new String("Hello");

    System.out.println(str1);
    System.out.println(str2.toString());
    //String클래스에 toString메서드는 이미 오버라이딩 되어 있음
    //그래서 참조 변수 출력시 Object의 toString형식(타입@주소값16진수)이 아니라 String의 저장된 문자열이 반환

    System.out.println(str1 == str2);
    //String객체의 주소값을 비교하기 때문에 false가 나옴

    System.out.println(str1.equals(str2));
    //String클래스에서 equals메서드도 이미 오버라이딩 되어있음(주소값비교가 아니라 문자열 값을 비교하도록)

    System.out.println(str1.hashCode());
    System.out.println(str2.hashCode());
    //String클래스에서 hashcode메서드도 이미 오버라이딩 되어있음(주소값이 아닌 문자열을 가지고 해시값을 비교하도록)

    //System.identityHashCode(참조변수)
    //해당 참조변수의 메모리값을 기반으로한 해시값을 반환
    System.out.println(System.identityHashCode(str1));
    System.out.println(System.identityHashCode(str2));

    System.out.println("---------------------------------------------------------------");

    //2. 문자열을 리터럴값으로 생성
    String str3 = "Hello";
    String str4 = "Hello";

    System.out.println(str3 == str4);
    //문자열 리터럴을 사용시 상수풀영역에 문자열을 생성한다.
    //String pool : 동일한 문자열을 중복해서 가지지 않는다.

    System.out.println(str3.hashCode());
    System.out.println(str4.hashCode());

    System.out.println(System.identityHashCode(str1));
    System.out.println(System.identityHashCode(str2));
    System.out.println(System.identityHashCode(str3));
    System.out.println(System.identityHashCode(str4));

    str3 = "Bye";
    System.out.println(System.identityHashCode(str3));
    System.out.println(System.identityHashCode(str4));
    //String 리터럴의 특성상 참조변수의 값을 변경하는 순간, 기존의 문자열 메모리의 값을 변경하는 것이 아니라
    //상수이기 때문에 새로운 값을 String pool에 만들고 참조하도록 되어 있음.
}

 

String은 Object에 있는 toString()을 오버라이딩을 하고 오버라이딩한 toString()은 저장한 String값을 반환하는 메서드이다


Wrapper클래스

기본자료형을 객체로 포장해 줄 수 있는 클래스

boolean(Boolean)

char(Char)

byte(Byte)

...

 

원시타입을 객체로 표현해야 할 경우 사용

  • 메서드의 매개변수로 전달해야할 때
  • 원시타입에도 다형성을 적용하고 싶을 때
public class WrapperAPI {
	public void method() {
		//Boxing : 기본자료형 -> Wrapper클래스 자료형
		int num1 = 10;
		int num2 = 20;
		
		System.out.println(num1 == num2);
		
		//1. 객체 생성구문 통해서 클래스 타입으로 변경
		Integer i1 = new Integer(num1);
		
		//2. 객체를 생성하지 않고 곧바로 대입(AutoBoxing)
		Integer i2 = num2; // new Integer(num1);
		
		System.out.println(i1.equals(i2));
		System.out.println(i1.equals(10));
		System.out.println(i1.compareTo(i2)); 
		//두 값을 비교해서 기준값이 크면 1, 전달값이 크면 -1, 동일하면 0 반환
		
		//문자욜을 Integer 타입으로 변환하고 싶을 때 -> 객체생성을 통해서 가능
		Integer i3 = Integer.parseInt("13");
		Integer i4 = new Integer("13");
		
		//Unboxing : Wrapper클래스 자료형 -> 기본자료형
		//1. Wrapper클래스에서 제공하는 xxxValue() 메서드 사용
		int num3 = i3.intValue();
		
		//2. 메서드 사용하지 않고 바로대입(AutoUnboxing)
		int num4 = i4;
		
		//int뿐만이 아니라 다른 자료형도 가능
	}
}

 

 

'JAVA' 카테고리의 다른 글

JAVA 13일차  (1) 2025.08.22
JAVA 12일차  (3) 2025.08.21
JAVA 9일차  (1) 2025.08.18
JAVA 8일차  (3) 2025.08.14
JAVA 7일차  (3) 2025.08.13