1. Stream
- InputStream(입력), OutputStream(출력) - ASCII, binary
- InputStream : FileInputStream, AudioInputStream, ObjectInputStream...
- OutputStream : FileOutputStream, AudioOutputStream, ObjectOutputStream...
- FileReader(입력), FileWriter(출력) - ASCII
InputStream
package io;
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
public class file14 {
public static void main(String[] args) {
try {
String url = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/agree3.txt";
File f = new File(url);
FileInputStream fs = new FileInputStream(f);
System.out.println(fs.available()); //fs.available() : 파일의 크기
byte data[] = new byte[fs.available()]; //파일의 크기만큼 배열 생성
fs.read(data); //Stream은 read안하면 아무것도 안나옴
String dataread = new String(data); //byte => String 변환해야함
System.out.println(dataread); //문자 출력
fs.close(); //잘 닫아주기!!
}catch(Exception e) {
System.out.println("경로 오류가 발생하였습니다.");
}
}
}
- Stream은 무조건 byte형태로 인식
- available() : 파일 전체 용량을 확인하는 메소드 //인터넷 첨부파일 크기같은거 이거로 핸들링
- read() : byte 전체를 읽어들이는 메소드 //안쓰면 아무것도 안나옴
- 출력시 byte -> String 변환 필수
OutputStream
package io;
import java.io.FileOutputStream;
//Stream (OutputStream)
public class file15 {
public static void main(String[] args) {
String url = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/test.txt";
String word = "[개인정보 보호 정책 약관]";
try {
FileOutputStream fs = new FileOutputStream(url,true);
byte[] data = word.getBytes(); //무조건 getBytes()로 String을 byte로 변환 후 Stream에 저장
fs.write(data);
fs.flush();//닫기전에 flush로 메모리를 비워줘야 계속 안잡아먹음 꼭 close랑 세트로 써주기
fs.close();
}catch(Exception e) {
System.out.println("해당 경로의 파일을 확인하지 못했습니다.");
}
}
}
- FileOutputStream : 파일에 사용자가 입력한 내용을 저장하는 기능
- true : 기존 데이터 보존하며 쓰기
- false(기본) : 새로운 데이터로 덮어쓰기
- 무조건 getBytes()로 String을 byte로 변환 후 Stream에 저장
- flush() :FileOutputStream은 close전 flush로 메모리를 무조건 비워줘야 함 //항상 close랑 세트로 써주기
😊응용문제
Stream 응용문제
구구단 9단을 dan.txt로 저장
package io;
import java.io.File;
import java.io.FileOutputStream;
public class file16 {
public static void main(String[] args) {
file16_box fb = new file16_box();
}
}
class file16_box{
public file16_box() {
String url = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/dan.txt";
String msg = "";
int i = 1;
while(i<=9) {
msg += "9 * "+i+" = "+ 9*i+"\n";
i++;
}
try {
File f = new File(url);
f.createNewFile();
FileOutputStream fs = new FileOutputStream(f);
byte[] data = msg.getBytes();
fs.write(data);
fs.flush();
fs.close();
}catch(Exception e) {
System.out.println("해당 경로의 파일을 확인하지 못했습니다.");
}
}
}
이미지 활용, 복사
package io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
//Stream으로 이미지를 활용하는 형태
public class file17 {
public static void main(String[] args) {
//원본이미지
String ori_img = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/ny.png";
try {
FileInputStream fs = new FileInputStream(ori_img);
// byte by[] = new byte[fs.available()]; //모두 복사
byte by[] = new byte[fs.available()/100];
// byte by[] = new byte[1024]; //작으면 엑박뜸 (부분복사 : 안쓰는거긴함)
// fs.read(by); //파일 이미지를 모두 읽어들임
//사본 이미지 경로 및 파일명
/*
jpg = jpeg != png
파일 복사시 속성 강제 변경은 오류 발생 가능
*/
String copy_img = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/"; //마지막에 슬래시를 써야 그 디렉토리 안에됨 /안쓰면 그 디렉토리를 불러오기함
FileOutputStream os = new FileOutputStream(copy_img+"img2.png");
// os.write(by); //원본 이미지를 복사 이미지로 copy
//progress 바 형태로 저장하는 방식 (로딩바)
int w = 0; //읽은 바이트 수
int check = 0; //읽은 횟수
while(true) {
w = fs.read(by); //전체 용량 / 100 => 전체 파일 용량을 나눠서 읽어들임 (사진의 용량이 큰 경우 로딩되는것은 기다려야함 부분부분하면 속도가 빨라짐)
if(w == -1) { //읽을 값이 없을 때
break;
}else {
//해당 byte만큼 지속적으로 이미지를 조합하여 사용하는 방식
//write(byte객체이름,0,읽은 byte숫자)
os.write(by,0,w); //원본 이미지를 복사 이미지로 copy
}
check++;
if(check % 2 == 0) { //progress 진행 상
System.out.println(check + "%");
}
}
os.flush();
os.close();
fs.close();
}catch(Exception e) {
System.out.println("해당 이미지 경로가 잘못되었습니다.");
}
}
}
- byte 변수명[] = new byte[FileInputStream변수명.available()] : 파일 크기만큼 byte할당
- FileInputStream변수명.read(byte변수명) : 파일 이미지를 모두 읽어들임
- FileOutputStream 변수명 = new FileOutputStream(복사본경로);
- FileOutputStream변수명.write(byte변수명) : 원본 이미지를 복사 이미지로 copy
여러개의 파일 복사
package io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class file18 {
public static void main(String[] args) {
img_copy ic = new img_copy();
}
}
class img_copy{
//원본 이미지 경로
String ori = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/";
//사본 이미지 경로
String dc = "/Users/nayeong/Documents/기타/copy/";
FileInputStream fs = null;
FileOutputStream os = null;
//복사할 파일명 리스트
String filenm[] = {"pd1.jpeg","pd2.jpeg","pd3.jpeg","pd4.jpeg"};
byte by[] = null; //파일을 읽어서 처리하는 변수
public img_copy() { //즉시실행
this.imgcopy(); //그냥 넘겨서 반복문에서 처리
}
public void imgcopy() { //이미지를 복사하는 메소드 (다른 경로)
try {
int w = 0;
while(w <this.filenm.length) {
//경로+파일명
this.fs = new FileInputStream(ori+this.filenm[w]);
this.by = new byte[this.fs.available()]; //용량만큼 byte배열 생성
this.fs.read(this.by); //byte용량을 모두 읽어들임
this.os = new FileOutputStream(dc+this.filenm[w]);
this.os.write(this.by); //해당 byte 용량에 맞춰서 저
this.os.flush(); //캐시 메모리 비우기 (안하면 메모리가 꽉차버릴수도있음 -> 문제발생)
w++;
}
System.out.println("해당 파일 전체를 모두 복사 완료하였습니다.");
}catch(Exception e) {
System.out.println("해당 파일중 경로 및 파일명이 올바르지 않습니다.");
}finally {
try {
this.os.close();
this.fs.close();
}catch (Exception e) {
System.out.println("파일이 올바르지 않습니다.");
}
}
}
}
속성 핸들링
package io;
import java.io.File;
public class attr {
public static void main(String[] args) {
String url = "/Users/nayeong/Documents/Eclipse/basic_html/src/main/java/io/ny.png";
File f = new File(url);
System.out.println(f.getName());
String filename = f.getName();
int n = filename.lastIndexOf(".");
System.out.println(n);
String modify = filename.substring(n);
System.out.println(modify);
String word2 = "홍길동 환영합니다. 포인트는 1000";
String sub = word2.substring(4,10);
System.out.println(sub);
}
}
- getName() : 파일명
- lastIndexOf() : 맨마지막부터 검토시 해당 단어의 인덱스
- IndexOf() : 맨앞부터 검토시 해당 단어의 인덱스
- substring(시작인덱스, 끝인덱스) : 단어를 자르는 메소드
파일 속성 및 디렉토리 리스트 + 다른 경로로 복사
package io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
public class file19 {
public static void main(String[] args) {
String dc = "/Users/nayeong/Documents/기타/copy/"; //원본 디렉토리
String dc2 = "/Users/nayeong/Documents/기타/copy2/"; //복사할 디렉토리 (미생성)
try {
File of = new File(dc);
File f = new File(dc2);
boolean result = f.mkdir();
File allfile[] = of.listFiles(); //해당 디렉토리에 모든 파일을 원시배열로 변환
System.out.println(Arrays.asList(allfile)); //asList도 toString도 둘다 가능
//attr.java 예시를 응용(필수로 알아야함)
int w = 0;
while(w<allfile.length) {
FileInputStream is = new FileInputStream(allfile[w]);
byte[] by = new byte[is.available()];
is.read(by);
//파일명을 다른 이름으로 변경
//lastIndexOf, IndexOf, substring 모두 다 문자열에만 사용
int n = String.valueOf(allfile[w]).lastIndexOf("."); //allfile의 자료형은 File이어서 변환시켜줘야함
//파일명 변환 파일명 형태 (예시 file0.jpeg)
String rename = "file" + w + String.valueOf(allfile[w]).substring(n);
System.out.println(rename);
//복사할 디렉토리에 변경된 파일명으로 저장
FileOutputStream fs = new FileOutputStream(dc2 + rename);
fs.write(by); //파일 저장
fs.flush(); //메모리 비우기
fs.close();
is.close();
w++;
}
System.out.println("모든 파일을 정상적으로 복사하였습니다.");
}catch(Exception e) {
System.out.println("디렉토리가 올바르지 않습니다.");
}
}
}
- mkdir() : make directory 디렉토리 생성 메소드
- delete() : 디렉토리,파일 삭제
- 자료형 잘 확인하기!
😊응용문제
http://mekeyace.dothome.co.kr/imgs.zip 즉시 다운
user 디렉토리에 이미지 압축 풀기
ftp 디렉토리에 이미지 복사
단, 2MB(2097152byte)이상 되는 이미지는 복사하지 않습니다.
또한 이미지 파일명을 다음과 같이 셋팅
cdn_0.속성명
cdn_1.속성명
cdn_2.속성명
...
이런 식으로 저장하기
내코드
package io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
public class file20 {
public static void main(String[] args) {
file20_box fb = new file20_box();
fb.copy_img();
}
}
class file20_box{
public void copy_img() {
String dc = "/Users/nayeong/Documents/java_etc/user/"; //원본 디렉토리
String dc2 = "/Users/nayeong/Documents/java_etc/ftp/"; //복사할 디렉토리 (미생성)
try {
File of = new File(dc);
File f = new File(dc2);
File allfile[] = of.listFiles(); //해당 디렉토리에 모든 파일을 원시배열로 변환
int w = 0;
int fn = 0;
while(w<allfile.length) {
FileInputStream is = new FileInputStream(allfile[w]);
if(is.available()>2097152) {
byte[] by = new byte[is.available()];
is.read(by);
//파일명을 다른 이름으로 변경
int n = String.valueOf(allfile[w]).lastIndexOf(".");
//파일명 변환
String rename = "cdn_" + fn + String.valueOf(allfile[w]).substring(n);
//복사할 디렉토리에 변경된 파일명으로 저장
FileOutputStream fs = new FileOutputStream(dc2 + rename);
fs.write(by); //파일 저장
fs.flush(); //메모리 비우기
fs.close();
is.close();
fn++;
}
w++;
}
System.out.println("모든 파일을 정상적으로 복사하였습니다.");
}catch(Exception e) {
System.out.println("디렉토리가 올바르지 않습니다.");
}
}
}
선생님코드
package io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class file20_t {
public static void main(String[] args) {
new upload();
}
}
class upload{
String dir1 = "/Users/nayeong/Documents/java_etc/user/"; //원본 경로
String dir2 = "/Users/nayeong/Documents/java_etc/ftp/"; //사본 경로
FileInputStream fs = null; //해당 파일을 로드
FileOutputStream os = null; //해당 파일을 저장
byte[] file = null; //해당 파일의 크기는 byte로 분할하여 배열화
File arr[] = null; //원본 디렉토리 파일리스트를 저장하는 배열
Integer limit_size = 2097152; //파일 용량 제한 크기 (byte)
public upload() {
this.copyfile();
}
private void copyfile() {
File f = new File(this.dir1); //해당 디렉토리를 호출
// File f2 = new File(this.dir2); //파일크기, 디렉토리 생성, 삭제할때 씀 무조건쓰는건아님 그래서 여기서는 필요없음
this.arr = f.listFiles(); //해당 디렉토리에 파일을 모두 원시배열로 전환
// ArrayList<File> as = new ArrayList<File>(); //클래스배열도 사용 가능
int w = 0; //파일명을 0부터 순서대로 적용하기위한 변수
try {
for (File filenm : this.arr) { //foreach문 사용
this.fs = new FileInputStream(filenm); //FileInputStream -> 빨간줄이 뜬다면 항상 예외처리 확인!
if(this.fs.available() <= this.limit_size) { //파일 제한 용량 확인
this.file = new byte[this.fs.available()]; //파일 어떤 형태로 구분하여 로드 상황을 구성
this.fs.read(this.file);
int n = String.valueOf(filenm).lastIndexOf("."); //파일 속성 타입 .기준으로 가져옴 => 예시 .png .jpeg
String rename = "cdn_" + w + String.valueOf(filenm).substring(n);
//해당 원본 파일을 이름 변경하여 ftp 디렉토리에 복사
this.os = new FileOutputStream(this.dir2 + rename);
this.os.write(file);
this.os.flush();
this.os.close();
w++; //조건에 맞을 경우 +1 해서 파일명에 적용
}
this.fs.close(); //조건과 관계없이 해당 파일을 종료
}
System.out.println("2MB 이하의 이미지를 모두 복사 완료하였습니다.");
} catch (Exception e) {
System.out.println("경로및 파일을 확인해주시길 바랍니다.");
}
}
}
2. Buffered
Buffered + Stream (동영상)
버퍼를 사용했기 때문에 빠름!
package io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
//Buffered + Stream (동영상) : 빠름!
public class file21 {
public static void main(String[] args) {
file21_box fb = new file21_box();
fb.copys();
}
}
class file21_box{
String mp = "/Users/nayeong/Documents/java_etc/user/abc.mp4"; //영상 파일 경로
String dir = "/Users/nayeong/Documents/java_etc/ftp/"; //복사할 파일 경로
public void copys() {
try {
InputStream is = new FileInputStream(this.mp); //InputStream : 부모 클래스
BufferedInputStream bs = new BufferedInputStream(is); //스트림 아래에 버퍼 쓰기 순서 바뀌면 안됨
System.out.println(bs.available());
byte file[] = new byte[bs.available()]; //buffered의 임시 데이터를 byte로 변환
OutputStream os = new FileOutputStream(dir + "nymovie.mp4");
BufferedOutputStream bos = new BufferedOutputStream(os);
//buffered 사용한 방식
bs.read(file); //전체 파일을 모두 읽어들임
bos.write(file); //buffered로 저장함
bos.flush();
bos.close();
//buffered 미사용한 방식
// os.write(file); //해당 디렉토리에 다른 파일명으로 복사
// os.flush(); //메모리를 비우는 작업 //항상 버퍼 지워주기
os.close();
bs.close();
is.close();
}catch(Exception e) {
System.out.println("경로 및 영상 파일이 올바르지 않습니다.");
}
}
}
간단 상식
I/O (저용량) => WEB => io (Writer, Stream) - Spring, Spring-boot (MVC)
NIO (대용량) => WEB => Spring 5.x, Spring-boot 3.x => WebFlux (스프링, 스프링부트 신버전을 신기술 사용해야만 사용가능)
Spring MVC(동기처리 방식) - 블로킹 방식 => 그래서 I/O만 사용 가능
Spring WebFlux(비동기처리 방식) - No블로킹 => NIO 사용 가능
=> NIO로 처리하려면 WebFlux를 공부하기
하지만 NIO는 코드가 상당히 복잡함
I/O가 어느정도 자리잡히면 그 이후에 공부하기
jpg == jpeg
WEB SERVER => HTML, CSS, JS, Tomcat, JSP ...
CDN SERVER => 이미지, 동영상 등 파일 서버
DB SERVER => Database 전용 서버
API SERVER => REST, RESTful
RTSP/RTMP SERVER => 스트리밍 서버
WebRTC SERVER => 스트리밍 서버
서버 따로 둠 클라우드 사용
클라우드할때 배웁니당
첨부파일 기능을 만들때 jsp파일 같은거는 못넣게 해야함
웹에서 실행하면 해킹 가능해서 확장자 잘 핸들링하기
사용자가 확장자를 지우고 올린 파일의 경우도 처리해야함 -> 어케할까용~
첨부파일 : 이미지만 업로드 가능합니다.
.png .bmp .jpg .jpeg .gif .webp ( + .tiff)
요정도 허용해줌
동영상
.avi .mpeg4 .webm .mp4 .mov
그리고 제한 용량이 2메가라고 해도 개발자들이 용량 살짝 널널하게 설정해둠