본문 바로가기
IT /1) 자바

자바독학) 파일 저장, IO, file, write, Stream(InputStream, OutputStream)

by 세세tv 2019. 11. 1.

 

프로젝트명 : H2_IO

패키지명 : file

클래스명 : B1_File

 

IO를 배우겠습니다!!

Input, Output의 줄임말로 입출력을 위한 스트림입니다.

 

Stream이란?

데이터를 입출력하기 위한 통로!

데이터가 이동하는 통로라고 생각해주세요!!

 

JVM에서 콘솔로 값을 내보내면 Output

콘솔에서 JVM이 값을 받으면 Input입니다

 

여기서 JVM이란?

자바의 가상 머신입니다.

프로그램에 필요한 메모리를 용도에 따라 

여러 영역으로 나누는 놈인데

 

자세히 파고들면 좀 어렵습니다!

 

파일을 쓰거나, 읽어 들이는 형태를 IO라고 합니다.

 

 

 

가볍게 File부터 보겠습니다.

String path = "E:\\JAVA/file"

 

폴더, 파일을 구분하는 것은,

역슬래시 두 개\\

혹은

슬래시 한 개/입니다.

 

폴더를 하나 들어가서 빨간 체크 부분에 커서를 두시면

폴더의 주소가 나옵니다 복사해서

path에 넣어주겠습니다.

 

path의 주소 값을 보면

E 드라이브에 JAVA폴더의 file폴더입니다.

 

 

해당 폴더에 메모장 하나 만들었습니다

메모장 이름 : test.txt

메모장에는 뭐 크게 의미 없는 내용을 넣었습니다.

 

FIle f = new File(path);

 

File을 import 하고 path의 경로를 주었습니다.

 

if(f.isFile){  f.length출력  }

.isFile = 파일 클래스의 경로가 파일인지 확인합니다.

 

경로가 폴더인 경우 else문이 출력됩니다

 

String path에  + /test.txt를 넣어주겠습니다.

f에 텍스트 파일을 지정해줘야겠죠?

 

 

출력 결과입니다.

 

length의 경우 파일의 크기를 출력합니다.

안녕하세요. 자바독학 블로그입니다.

 

한글 15개 * 2바이트 = 30바이트

점. 2개 * 1바이트 = 2바이트

띄어쓰기 2개 * 1바이트 = 2바이트

 

총 34바이트의 결과가 나왔습니다.

 

메모장에서 우클릭 속성을 눌러보시면

크기가 콘솔창과 일치한 것을 볼 수 있습니다.

 

 

path의 경로를 폴더까지만 잡아보겠습니다.

 

f.isDirectory를 통해 폴더의 여부를 확인합니다.

 

String[] names = f.list();

폴더에 있는 내용을 names배열에 하나씩 추가합니다.

 

for문을 사용하여 names[i]를 출력하면

path의 경로에 있는 폴더 혹은 파일을 모두 출력합니다.

 

경로가 파일인 경우는 else문으로 이동하게 됩니다.

 

 

클래스명 : B2_File2

 

클래스 하나 더 생성하겠습니다.

존재하지 않는 폴더를 path에 넣어보겠습니다.

 

String path = "E:/JAVA/file/ccc";

ccc라는 폴더를 생성하지 않았습니다!

 

if , else문을 이용하여

f.isDirectory()를 확인해보면

폴더가 없다고 출력됩니다.

 

폴더를 생성하는 방법입니다.

 

if(!f.exists()){ 

f.mkdirs();

}

 

.exists()는 '존재한다'입니다

앞에 !를 붙이면 '존재하지 않는다'겠죠?

 

mkdirs()는 폴더를 생성합니다.

 

path의 경로에서 ccc는 존재하지 않는 폴더였습니다.

mkdirs()를 사용하면 자동으로 폴더가 생성됩니다.

 

mkdir도 있는데 폴더가 하나만 생성되고

mkdirs는 여러 개 되고 하는데

 

굳이 좋은 거 두고 쓰지 않을 이유가 없으니

mkdirs()만 알고 계시면 됩니다. 

 

 

 

file패키지에서 클래스와 인터페이스 생성하겠습니다

 

클래스명 : B3_File3

인터페이스명 : FilePath

 

인터페이스에서 String PATH = "E:/JAVA/file"

미리 저장해 두고 사용하겠습니다.

 

인터페이스니 상수로 만드셔야겠죠?

final은 생략해도 좋다고 말씀드렸습니다.

 

 

B3_File3로 이동하겠습니다.

 

String path = FilePath.PATH + "/test.txt";

 

이렇게 기본적인 폴더에서 +를 사용하여 폴더 혹은 파일을

추가하시면 편하겠죠???

 

File f= new File(path);

File f에 경로를 넣어주었습니다.

 

if(f.exists())를 통해 존재 여부를 확인하겠습니다.

존재 여부는 필수입니다! 오류 나거든요!!

 

FileInputStream 보겠습니다

파일에 있는 내용을 읽어보는 클래스입니다.

 

FileInputStream fis = new FileInputStream(f);

소괄호 내부에 f를 넣어 경로에 있는 txt의 내용을 읽어옵니다.

 

FileInputStream의 경우

try/catch로 묶어줘야 합니다!

 

FileNotFoundException오류 때문인데

파일을 찾지 못하는 오류 등 

Stream통로를 이동 중 등

 

오류가 발생할 수 있습니다.

 

 

 

int code를 생성하여

 

while문의 조건에

(code = fis.read()) != -1

 

fis.read를 통해 1바이트씩 내용을 읽어옵니다.

code에 내용을 넣어서 -1이되면 종료합니다

 

아무 값이 없는 경우 -1이 되어

while은 종료됩니다.

 

code를 char타입으로 형변환 하여 출력해보겠습니다.

 

 

콘솔을 보면 이상한 값을 가져옵니다.

1바이트씩 가져오기에

 

저 위의 내용을 합치면 되는데

헷갈리네요!

 

우선 해봅시다!

 

if(fis != null)을 통해

파일에 내용이 있다면!

fis.close();를 통해 통로를 잡아주어야 합니다.

 

가끔 폴더 삭제하면

현재 사용 중인 폴더입니다.

라면서 삭제가 안된 적이 있나요?

 

그게 실제로는 종료된 것처럼 보이지만

백그라운드에 남아있어서 그렇습니다.

 

그렇기에 꼭! 지워줍시다.

d

 

int code에 저장하지 말고

byte배열을 만들겠습니다.

 

byte[] b_read = new byte[(int) f.length];

b_read에 f의 바이트만큼 공간을 만들겠습니다.

 

fis.read(b_read);

.read를 통해 b_read에 넣어주겠습니다.

 

String res에 b_read를 넣어주겠습니다.

res를 출력해보면 잘 출력됩니다.

 

 

패키지명 : input

클래스명 : B1_Fileinput

 

[ IO ]

byte기반의 Stream

char기반의 Stream

 

Stream의 두 종류입니다.

 

....Stream의 경우 byte 기반입니다.

....Writer, ....Reader의 경우 char 기반입니다.

 

저는 대부분 char기반의 Stream을 사용하기에

byte의 사용 용도는 잘 모르겠네요...

 

일단 알려는 드리겠습니다!

 

 

 

FileinputStream fis를 생성하겠습니다.

 

Stream으로 끝나니 byte기반입니다!

 

byte[]배열을 통해 read와 console 각 100개씩 만들겠습니다.

 

try/catch를 통해 예외처리를 하고

 

경로를 콘솔에서 입력해보겠습니다.

System.in.read(console);

System.in = 시스템 안에서

.read = 읽는다

console = byte배열의 console을 한 글자씩

 

콘솔에서 System.in을 통해 입력한 값을

.read를 통해 한 글자씩 가져옵니다.

 

 String path를 생성하여 console을 저장하고

.trim()을 통해 여백을 모두 잘라줍니다.

 

console의 경우 100개의 배열이 있으니 잘라줘야 합니다.

 

fis.read(read);

fis의 내용을 하나씩 읽어와

read배열에 저장합니다.

.trim()을 통해 여백은 잘라줍니다.

 

finally를 통해 통로를 닫아주겠습니다

파일이 있던 없던 통로가 열렸으면 닫아야 하니

finally에 작성하겠습니다.

 

 

BufferdStream 배우겠습니다.

적용법은 간단한 편이며 속도가 빠릅니다!

 

FileInputStream에 연결하는 방식입니다.

버퍼링을 한 번씩을 들어봤으며 대충 내용을 아시죠??

 

정확히는 메모리 공간에 정렬을 해놓고 한 번에 내보냅니다.

가끔 영상을 느린 데이터로 보면

 

버퍼링이 걸렸다가 30초 정도 보면 또

버퍼링 걸리고 그러죠?

 

그렇게 모아서 한 번에 뿌리는 형식이 모두

BufferdStream입니다.

 

메모리를 모으는 전용공간이 있다고

생각해주시면 좋겠습니다.

 

 

 

기존 내용에 작성하겠습니다.

 

위쪽에 BufferedInputStream bis 생성하여 null값 넣었습니다.

 

fis에 path의 경로를 담고!

bis에는 fis를 담아주겠습니다.

 

bis.read(read);를 통해

buffered스트림으로 읽어주겠습니다.

 

스트림을 닫을 때는 꼭!

bis를 먼저 닫아주어야 합니다.

bis는 닫힐 때,

fis의 통로를 통해서 닫히게 됩니다.

 

fis가 먼저 닫히는 경우

bis는 나갈 공간이 없어 통로가 닫히지 않습니다.

 

정상적인 종료가 불가능하겠죠?

 

 

패키지명 : output

클래스명 : B1_OutPut

 

PrintStream ps = null;

PrintStream은 OutputStream의 대표적인 자식 클래스 중 하나입니다.

화면에 데이터를 출력하도록 하는 클래스입니다.

 

ps = System.out; 해보겠습니다.

 

int형으로 'A' , 'B' 두 개를 저장하겠습니다.

실제로는 아스키코드로 저장되겠지만!

 

write를 사용하여 출력하면 AB가 출력됩니다.

그냥 알고만 계시면 됩니다.. ㅎㅎ

 

 

 

클래스명 : B2_FileOutputStream

 

FileOutputStream fos = null;

 

try/catch를 사용하여

fos에 경로를 넣어주겠습니다.

 

String msg를 생성하여 문장을 넣어주겠습니다.

byte[]타입의 res에 msg를 저장하기 위해

getBytes()를 사용하여 문자열을 바이트 배열로 변환합니다.

 

fos.write(res);를 이용하여 내용을 작성합니다.

test.txt의 내용에는 현재

"파일 output 스트림의 예제"

이렇게 저장되어있네요??

 

finally에서 꼭 .close();를 통해

통로를 닫아줍시다.

 

 

실행하시면 txt의 내용이 변경됩니다.

 

buffered를 사용하는 방법도 알아야겠죠?

 

fos 만들면서 bos도 생성해주고

fos에는 경로

bos에는 fos를 담아주고

bos에서 write 해주시면 됩니다.

 

그냥 BufferedOutputStream만 추가하고

크게 어려운 내용은 없으니

이왕 할 거 빠르게! 하시면 됩니다.

 

뭐 txt 읽는 것 정도야 그냥 해도 빠르지만!

익숙해질 겸 계속 사용하시면 됩니다.

 

이번 내용이 어려운 분들은 

더 자주 사용하는 방법으로 다음 포스팅에서 알려드리겠습니다.

 

저는 개인적으로

Stream = byte보다는

Write, Read를 사용하는 것을 좋아합니다.

 

애초에 더 쉬워요..

솔직히 byte배열로 사용하는 거 어렵잖아요 ㅜ

용도도 잘 모르겠고..

댓글