상세 컨텐츠

본문 제목

[인턴 OJT 3일차] Static, File I/O, Static, bit/byte

인턴

by 리잼 2022. 12. 14. 22:07

본문

반응형

 

1. 자바 File class

절대 경로

c:\Program Files\Java 와 같은 표기법 최상위 dir 경로가 포함되어야 한다.

상대 경로

특정 파일이나 폴더를 기준으로 상재적으로 주소를 표현

 

File class 란?

파일에 대한 정보들을 파악하기 위한 메소드들로 구성되어 있다.

파일을 생성하고 삭제하며 지정된 파일이 읽기 가능한지, 현재 디렉토리에 어떤 파일들이 있는지 검사할 수 있다.

파일과 디렉토리를 다룰 수 있으며, File instance는 File일 수도 디렉토리 일 수도 있다.

 

File Class Method 정리

	public static void main(String[] args) throws IOException {

		File file = new File("data/HelloWorld.txt");
		
		LOGGER.debug("====클래스의 조회 관련 메서드====");
		LOGGER.debug("file.getAbsoluteFile() = " + file.getAbsoluteFile()); //파일의 절대경로를 반환한다.
		LOGGER.debug("file.getAbsolutePath() = " + file.getAbsolutePath()); //파일의 절대경로를 문자열로 반환한다.
		LOGGER.debug("file.getCanonicalFile() = " + file.getCanonicalFile()); //파일의 정규 경로를 반환한다.
		LOGGER.debug("file.getName() = " + file.getName()); //파일이나 폴더의 이름을 넘겨준다.
		LOGGER.debug("file.getParent() = " + file.getParent()); //부모경로에 대한 경로명을 문자열로 반환한다.
		LOGGER.debug("file.getParentFile() = " + file.getParentFile()); //부모 폴더를 File의 형태로 반환한다.
		LOGGER.debug("file.getPath() = " + file.getPath()); //파일의 경로를 문자열의 형태로 반환한다.
		LOGGER.debug("file.hashCode() = " + file.hashCode()); //해쉬코드를 반환한다.
		LOGGER.debug("file.length() = " + file.length()); //해당 경로파일의 길이를 반환한다.
		LOGGER.debug("file.toURI() = " + file.toURI()); //URI형태로 파일경로를 반환한다.
		
		LOGGER.debug("====파일 체크 관련 메서드====");
		LOGGER.debug("file.exist() = " + file.exists()); //파일의 존재 여부를 반환한다.
		LOGGER.debug("file.isAbsolute() = " + file.isAbsolute()); //해당 경로가 절대경로인지 여부를 반환한다.
		LOGGER.debug("file.isDirectory() = " + file.isDirectory()); //해당 경로가 디렉토리인지 여부를 반환한다.
		LOGGER.debug("file.isFile() = " + file.isFile()); //해당 경로가 file인지 여부를 반환한다.
		LOGGER.debug("file.isHidden() = " + file.isHidden()); //해당 경로가 숨김 파일인지 여부를 반환한다.
		
		LOGGER.debug("====파일 권한 관련 메서드====");
		LOGGER.debug("file.canExecute() = " + file.canExecute()); //파일 실행 권한이 있는지 여부를 반환한다.
		LOGGER.debug("file.canRead() = " + file.canRead()); //파일 읽기 권한이 있는지 여부를 반환한다.
		LOGGER.debug("file.canWrite() = " + file.canWrite()); //파일 작성 권한이 있는지 여부를 반환한다.
		LOGGER.debug("file.setReadOnly() = " + file.setReadOnly()); //파일을 읽기 전용으로 변경한다.
		
	}

2022-12-14 13:10:23.864 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(17) ====클래스의 조회 관련 메서드====
2022-12-14 13:10:23.867 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(18) file.getAbsoluteFile() = C:\Users\flash\git\OJT2022\data\HelloWorld.txt
2022-12-14 13:10:23.867 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(19) file.getAbsolutePath() = C:\Users\flash\git\OJT2022\data\HelloWorld.txt
2022-12-14 13:10:23.868 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(20) file.getCanonicalFile() = C:\Users\flash\git\OJT2022\data\HelloWorld.txt
2022-12-14 13:10:23.868 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(21) file.getName() = HelloWorld.txt
2022-12-14 13:10:23.868 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(22) file.getParent() = data
2022-12-14 13:10:23.869 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(23) file.getParentFile() = data
2022-12-14 13:10:23.869 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(24) file.getPath() = data\HelloWorld.txt
2022-12-14 13:10:23.869 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(25) file.hashCode() = 1003209317
2022-12-14 13:10:23.869 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(26) file.length() = 125
2022-12-14 13:10:23.869 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(27) file.toURI() = file:/C:/Users/flash/git/OJT2022/data/HelloWorld.txt
2022-12-14 13:10:23.869 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(29) ====파일 체크 관련 메서드====
2022-12-14 13:10:23.870 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(30) file.exist() = true
2022-12-14 13:10:23.870 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(31) file.isAbsolute() = false
2022-12-14 13:10:23.870 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(32) file.isDirectory() = false
2022-12-14 13:10:23.870 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(33) file.isFile() = true
2022-12-14 13:10:23.871 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(34) file.isHidden() = false
2022-12-14 13:10:23.871 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(36) ====파일 권한 관련 메서드====
2022-12-14 13:10:23.871 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(37) file.canExecute() = true
2022-12-14 13:10:23.871 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(38) file.canRead() = true
2022-12-14 13:10:23.872 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(39) file.canWrite() = false
2022-12-14 13:10:23.872 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.FileClassTest(40) file.setReadOnly() = true
 

2. InputStream / OutputStream

입출력 스트림

- 네트워크에서 자료의 흐름이 물의 흐름과 같다는 비유에서 유래됨

- 자바는 다양한 입출력 장치에 독립적으로 일관성있는 입출력 스트림을 통해 제공

- 입출력이 구형되는 곳 - 파일디스크, 키보드, 마우스, 네트웍, 메모리 등 모든 자료가 입력되고 출력되는 곳

입출력 스트림의 구분

- 대상 기준 : 입력 스트림 / 출력 스트림

- 자료의 종류 : 바이트 스트림 / 문자 스트림

- 기능 : 기반 스트림 / 보조 스트림

스트림의 종류

입력 스트림 : FileInputStream, FileReader, BufferedInputStream, BufferedReader 등

출력 스트림 : FileOutputStream, FileWriter, BufferedOutputStream, BufferedWriter 등

 

바이트 단위 스트림과 문자 단위 스트림

- 바이트 단위 스트림 : 동영상, 음악, 파일, 실행 파일 등 자료를 읽고 쓸 때 사용

- 문자 단위 스트림 : 바이트 단위로 자료를 처리하면 문자는 깨짐,

- 인코딩에 맞게 2바이트 이상으로 처리하도록 구현된 스트림

스트림의 종류

바이트 스트림 : FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등

문자 스트림 : FileReader, FileWriter, BufferedReader, BufferedWriter 등

 

기반 스트림과 보조 스트림

- 기반 스트림 : 대상에 직접 자료를 읽고 쓰는 기능의 스트림

- 보조 스트림 : 직접 읽고 쓰는 기능은 없이 추가적인 기능을 더해주는 스트림

- 보조 스트림은 직접 읽고 쓰는 기능은 없으므로 항상 기반 스트림이나

또 다른 보조 스트림을 생성자의 매개 변수로 포함함

 

스트림의 종류

기반 스트림 : FileInputStream, FileOutputStream, FileReader, FileWriter 등

보조 스트림 : InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream 등

 

InputStream / OutStream

- 바이트 단위 입력 스트림 최상위 추상 클래스

- 많은 추상 메서드가 선언되어 있고 이를 하위 스트림이 상속받아 구현함

 

주요 하위 클래스

- FileInputStream : 파일에서 바이트 단위로 자료를 읽습니다.

- ByteArrayInputStream : byte 배열 메모리에서 바이트 단위로 자료를 읽습니다.

- FilterInputStream : 기반 스트림에서 자료를 읽을 때 추가 기능을 제공하는 보조 스트림의 상위 클래스

 

주요 메서드

- int read() : 입력 스트림으로부터 한 바이트의 자료를 읽습니다. 읽은 자료의 바이트 수를 반환합니다.

- int read(byte b[]) : 입력 스트림으로 부터 b[] 크기의 자료를 b[]에 읽습니다. 읽은 자료의 바이트 수를 반환합니다.

- int read(byte b[], int off, int len) : 입력 스트림으로 부터 b[] 크기의 자료를 b[]의 off변수 위치부터 저장하며

len 만큼 읽습니다. 읽은 자료의 바이트 수를 반환합니다.

- void close() : 입력 스트림과 연결된 대상 리소스를 닫습니다.

 

FileInputStream의 주요 메서드는 read()로 매개변수가 없으면 파일에서 1Byte씩 읽게된다.

 

 
예제 파일

 

public static void main(String[] args) {

		File file = new File("data/TextTest.txt");
		
		InputStream inputStream = null;
		try {
			inputStream = new FileInputStream(file);
			
			byte[] buf = new byte[21];
			inputStream.read(buf);
			
			LOGGER.debug(String.format("readData:[%s] ", new String(buf)));
			
			
		} catch (FileNotFoundException fnfe) { // 파일이 없는경우 예외
			LOGGER.error(fnfe.getMessage());
		} 
		
		catch (IOException ioe) { // 입출력에 문제가 있는경우 예외
			LOGGER.error(ioe.getMessage());
		}
		finally {
			if (inputStream != null) {
				try {
					inputStream.close(); // 필수
				}
				catch (IOException ioe) {
					LOGGER.error(ioe.getMessage(), ioe);
				}
			}
		}
		
	}
2022-12-14 14:33:12.183 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.InputStreamTest(27) readData:[Hello
Wor] 
 

코드를 보면 Hello wor 이 찍히는데 \r\n이 각각 1byte씩 이므로 위와 같은 출력이 나오게 된다.

UTF-8 인코딩에서 한글은 3byte 씩 읽히기 때문에 값을 5byte로 주게 되면

 
 
이름을 적고 5byte를 주었다

한글이 깨져서 출력되므로 인코딩에 주의 해야한다 / euc-kr 한글은 2byte 할당.

출력을 마치면 꼭 close()로 스트림을 닫아줘야 한다.

하지만 close를 위해서 try-catch-finally 구문을 모두 작성하다보면 코드가 너무 길어지고 가독성이 떨어지게 되는데

자바에서 이것을 해결해 주었다.

public static void main(String[] args) {
		
		byte[] buf = new byte[10];

		File srcFile = new File("data/TextTest.txt");
		File destFile = new File("data/TextTest2.txt");
        // try괄호 안에 stream을 사용하면 finally를 작성하지 않아도 close()를 사용한것과 동일하다.
		try (InputStream inputStream = new FileInputStream(srcFile);
				OutputStream outputStream = new FileOutputStream(destFile)) {
			int readNum = 0;
			while ((readNum = inputStream.read(buf)) > 0) {
				outputStream.write(buf, 0, readNum);
			}
		}
		catch (FileNotFoundException fnfe) {
			LOGGER.error(fnfe.getMessage(), fnfe);
		}
		catch (IOException ioe) {
			LOGGER.error(ioe.getMessage(), ioe);
		}

	}
 

문자단위 입력 스트림

Reader

- 문자 단위 입력 스트림 최상위 추상 클래스

- 많은 추상 메서드가 선언되어 있고 이를 하위 스트림이 상속받아 구현함

 

주요 하위 클래스

- FileReader : 파일에서 문자 단위로 읽는 스트림 클래스입니다.

- InputStreamReader : 바이트 단위로 읽은 자료를 문자로 변환해주는 보조 스트림 클래스 입니다.

- BufferedReader : 문자로 읽을 때 배열을 제공하여 한꺼번에 읽을 수 있는 기능을 제공하는 보조 스트림입니다.

 

주요 메서드는 InputStream과 같다.

	public static void main(String[] args) {

		char[] buf = new char[20];

		File file = new File("data/TextTest.txt");
		try(FileReader reader = new FileReader(file)) {
			
			reader.read(buf);
			LOGGER.debug(String.format("reader : %s ", new String(buf)));

			
		} catch (FileNotFoundException fnfe) {
			LOGGER.error(fnfe.getMessage());

		} catch (IOException ioe) {
			LOGGER.error(ioe.getMessage());
		}

	}
2022-12-14 17:09:09.609 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.InputStreamTest(56) reader : Hello
World
이재민
 

BufferedReader / BufferedWriter

- 버퍼를 통해 읽고 쓰는 함수

- 입출력 데이터가 바로 전달되지 않고 중간에 버퍼링이 된 후 전달된다

- 속도가 빠름

주요 용어

Buffer

데이터를 한 곳에서 다른 하나 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 임시 메모리 영역

입출력 속도 향상을 위해 버퍼 사용

Buffer flush

버퍼에 남아 있는 데이터를 출력시킴(버퍼를 비우는 동작)

BufferReader / BufferWriter

버퍼를 이용한 입출력

	public static void main(String[] args) {

		File file = new File("data/TextTest.txt");
		
		List<String> repo = new ArrayList<>();

		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String readLine = null; // readline으로 한줄씩 읽어오기가 가능
			while ((readLine = reader.readLine()) != null) {
				LOGGER.debug(String.format("readData:[%s]", readLine));
				
				repo.add(readLine);
			}
		}
		catch (FileNotFoundException fnfe) {
			LOGGER.error(fnfe.getMessage(), fnfe);
		}
		catch (IOException ioe) {
			LOGGER.error(ioe.getMessage(), ioe);
		}
		finally {
			if (reader != null) {
				try {
					reader.close();
				}
				catch (IOException ioe) {
					LOGGER.error(ioe.getMessage(), ioe);
				}
			}
		}
		
		File f2 = new File("data/HelloWorld2.txt");
		try (Writer writer = new FileWriter(f2)) {
			//문자열이 만나면 결합하게 하는함수 \n 으로 개행
			String s = StringUtils.join(repo, "\n");  
			
			writer.write(s);
		}
		catch (FileNotFoundException fnfe) {
			LOGGER.error(fnfe.getMessage(), fnfe);
		}
		catch (IOException ioe) {
			LOGGER.error(ioe.getMessage(), ioe);
		}
		
	}
2022-12-14 17:26:42.468 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.ReadWriterTest(33) readData:[Hello]
2022-12-14 17:26:42.470 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.ReadWriterTest(33) readData:[World]
2022-12-14 17:26:42.470 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.ReadWriterTest(33) readData:[이재민]
 

Static

정적(static)은 고정된이란 의미를 가지고 있음

Static 키워드를 통해 생성된 정적멤버들은 Heap영역이 아닌 Static영역에 할당

Static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가짐

하지만 Garbage Collector의 관리 영역 밖에 존재하기에 Static영역에 있는 멤버들은 프로그램의 종료시까지 메모리가 할당된 채로 존재하게된다.

너무 남발하게 되면 시스템 성능에 악영향을 주므로 null로 레퍼런스를 재선언해야함

 

 

static 멤버 선언

static int num = 0; //타입 필드 = 초기값
public static void static_method(){} //static 리턴 타입 메소드 {}
 

static 필드 사용 예시

class Number{
    static int num = 0; //클래스 필드
    int num2 = 0; //인스턴스 필드
}

public class StaticTest {

	private static Logger LOGGER = LoggerFactory.getLogger(ReadWriterTest.class);

	
	public static void main(String[] args) {

		    Number number1 = new Number(); //첫번째 number
		    Number number2 = new Number(); //두번쨰 number
		    	
		    number1.num++; //클래스 필드 num을 1증가시킴
		    number1.num2++; //인스턴스 필드 num을 1증가시킴
		    LOGGER.debug("number2 : " + number2.num); //두번째 number의 클래스 필드 출력
		    LOGGER.debug("number2 : " + number2.num2);//두번째 number의 인스턴스 필드 출력
		    
	}

}
2022-12-14 17:51:16.496 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.ReadWriterTest(23) number2 : 1
2022-12-14 17:51:16.498 [DEBUG] [      main] com.barunsw.ojt.jmlee.day03.ReadWriterTest(24) number2 : 0
 

static 메서드 사용 예시

class Name{
    static void print() { //클래스 메소드
	System.out.println("내 이름은 이재민입니다.");
    }

    void print2() { //인스턴스 메소드
	System.out.println("내 이름은 이재민2입니다.");
    }
}

public class StaticTest2 {
	
	private static Logger LOGGER = LoggerFactory.getLogger(ReadWriterTest.class);

	public static void main(String[] args) {
		
		 Name.print(); //인스턴스를 생성하지 않아도 호출이 가능
	    	
	     Name name = new Name(); //인스턴스 생성
	     name.print2(); //인스턴스를 생성하여야만 호출이 가능

	}

}
 

정적 메소드는 클래스가 메모리에 올라갈 때 정적 메소드가 자동적으로 생성된다.

그렇기에 정적 메소드는 인스턴스를 생성하지 않아도 호출을 할 수 있고,

정적 메소드는 유틸리티 함수를 만드는데 유용하게 사용된다.

 

Bit / Byte

 

bit = binary digit의 약어

컴퓨터가 정보를 처리하는 단

기본적으로 디지털 신호의 자리 표시자

 

byte / 1byte = 8bit

컴퓨터가 실제 사용할 수 있는 데이터 중 가장 작은주소

숫자, 글자, 로마자 등의 표현을 위한 기본단위이다.

바이트는 2진수 및 10진수 접두어가 비트 : 1kb = 1024byte와 동일한 불일치로 인해 어려움을 겪는다.

 

데이터 기억용량 단

사진 삭제
  • 오른쪽 정렬왼쪽 정렬가운데 정렬
  •  
  • 삭제

사진 설명을 입력하세요.

 

반응형

관련글 더보기

댓글 영역