본문 바로가기

JAVA

[이것이 자바다] 18.4 파일 입출력, Java Swing으로 채팅 구현

18.4.1 File 클래스

 

File 클래스를 이용한 파일 및 디렉토리 정보 출력

package k_io;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;

public class FileExam {

	public static void main(String[] args) throws URISyntaxException, IOException {
		File dir = new File("c:/Temp/Dir");
		File file1 = new File("c:/Temp/file1.txt");
		File file2 = new File("c:/Temp/file2.txt");
		File file3 = new File(new URI("file:///c:/Temp/file3.txt"));

		if (!dir.exists())
			dir.mkdirs(); //존재하지 않으면 생성
		if (!file1.exists())
			file1.createNewFile(); // 새로운 파일 생성
		if (!file2.exists())
			file2.createNewFile();
		if (!file3.exists())
			file3.createNewFile();

		File temp = new File("c:/Temp");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a HH:mm");

		File[] contents = temp.listFiles();
		// temp 경로 모든 파일을 contents에 넣음
		System.out.println("\t날짜 \t 시간\t 형태\t 크기\t 이름");
		System.out.println("--------------------");

		for (File file : contents) {
			System.out.print(sdf.format(file.lastModified()));

			if (file.isDirectory()) {
				System.out.print("\t<DIR>\t\t" + file.getName());
			} else {
				System.out.println("\t\t" + file.length() + "\t" + file.getName());
			}

			System.out.println();
		}
	}

}

 

FileExam2.java

2. 파일 복사하는 기능 구현

 

 

 

 

super ( ) 호출하지 않았을 경우

 

 

  • open : 파일 읽을때
  • save : 저장할때
  • 매개변수 Component : showOpenDialog가 포함되어 있는 객체 → FileCopy 자기자신을 컴포넌트로(null 하면 그냥 화면 중간에 뜸)

 

fileChooser 실행화면

 

  • FileChooser 상자가 FileCopy의 가운데에 뜨게 하고 싶을때

 

파일 선택하고 확인 누르면 original 텍스트필드에 파일명이 뜨도록

 

파일명 up

 

ProgressBar 매개변수로 받는 스레드
  • 원본&대상파일도 스레드로 전달 : 생성자로 전달 혹은 getter setter 사용

 

 

setter를 통해 값이 전달되지 않았는데 실행되는것을 방지하기 위해 (null이 아닐때만 복사 실행)

 

  • FileInputStream : original을 읽어들여라

    (여기서 original은 파일 선택상자에서 사용자가 선택한 파일의 path)

  • FileOutputStream : target 파일을 저장해라
  • readByteNo : 읽은 바이트 수
  • readBytes 배열 : 배열의 수만큼 original 파일을 읽는다

 

다음 읽을 데이터가 없으면 -1 → -1이 아닐때 루프를 돌도록
  • FileInputStream의 메소드인 read에 readBytes 배열 넣은 값 = 배열의 수(100) 만큼 읽고 읽은만큼 readyByteNo에 리턴하여 대입하는데, 다 읽고 더 이상 읽을 데이터가 없으면 -1을 리턴한다.
  • 즉, -1이 아닐때까지 데이터를 읽어들이고 저장

 

fos.write(읽혀진 데이터 있는 배열, 시작위치, 얼만큼 저장할 것인지)
  • 100 바이트씩 읽어들이기 때문에 readBytes라는 배열의 0부터 100까지의 배열을

 

복사 눌렀을때

 

 

 

 

 

복사되는중 (sleep 50 줬을때)

 

 

 

 

TextEditor.java (InternalFrame)

 

border → scrollPane → TextArea

 

기본셋팅

 

기본세팅2 (메인에서)

 

 

 

메인에서 세팅3
  • flag : 확인버튼 눌렀는지, 취소버튼 눌렀는지 판단하는 정수
  • 눌렸으면 선택된 파일명을 fileName에 담고 textEditor에 해당 파일 이름 전달

 

UI보내고, fileName 필드로 전달, load 메소드 호출

 

 

 

 

  • 보완점
  1. 읽어들인 파일명 상단에 표시
  1. 항목 수정하면 제목에 '수정됐다'는 기호로 표시
  1. 저장하면 마킹 없애기

 

파일명 타이틀에 표시하기

 

"새로만들기" → 생성자 없는 TextEditor

 

키보드이벤트

 

 

 

 

 

 

ClientFrame.java (JFrame, Runnable 상속)

Server와 마찬가지로 접속 누르면 스레드 생성하고 메인과 별개로 작업스레드가 실행될 수 있도록
  • ClientFrame extends JFrame : is a (본인도 JFrame)
  • ClientFrame implements Runnable : is a (본인도 Runnable)
  • ClientFrame이 가지고 있는 멤버들은 has a 관계
  • 에러메시지 : run 메소드 정의 필요

 

 

  • ClientFrame.this : 자동으로 Thread가 runnable을 가져온다.
  • 여기서 그냥 this 하면 new ActionListener를 호출함

 

 

run 메소드에 소켓 생성해서 ip주소, 포트번호 넣기

 

 

 

textPane

 

 

font 태그의 범위
  • RGB 색상 : #RRGGBB (red 00 ~ ff, green 00 ~ ff, blue 00 ff) ff : 255
  • 결국은 빨간색에 글자크기 5사이즈 (1~7사이즈)

 

  • #ffffff : 흰색
  • #000000 : 검정색
(doc, 시작위치 (doc의 length), 문자열, ... 나머지는 0 혹은 null)

 

try에 html로 메시지 출력 (1)
출력화면

 

 

  • div : 문단 (화면 수정 : 끝에 /div)
  • style : CSS 적용
  • border : 외곽선 (굵기 px)
  • solid : 선의 종류
  • 선의 색
  • padding : 안쪽의 여백 (외곽과 글자 사이의 여백)
  • width : 외곽선의 넓이

 

 

실행화면 (border 5px;;)

 

스크롤 알아서 내려주는 기능 추가

  • 해당 매개변수 Rectangle 타입이라 바로 객체 생성하기

 

 

바닥에 내려감

 

메시지보내기

 

  • 채팅클라이언트 창에서 아이디와 암호를 묶어서 서버에 보내고 접속을 누르면, 서버에서 Park 접속한 상태 표시되도록.
  • 접속한 후에 가장 먼저 하는 일 : 자기자신 정보를 서버에 던져서 서버 접속자 목록에 뿌려주기
  • 클라이언트 접속목록에는 아직 표시하지 못 함 (서버로부터 아직 못 받아서)
  • command : 메시지인지 로그인정보인지 종료버튼 눌렀는지 판단
  • 접속자 목록 : List

 

 

ChatDate 만들어서 상수 정하고 직렬화

 

필드는 모두 getter, setter 만든다

 

다시 ClientFrame

  • InputStream, OutputStream 만들 때 출력스트림 먼저, 입력스트림 나중에.
  • socket만으로는 연결하는데 무리가 있어서 socket 메소드 getInput, outputStream 활용 → Object input, output Stream 만들것임

 

 

 

 

어차피 로그인 메소드가 try catch 안에 있으니까 예외처리 미뤄도 됨

 

로그인 메소드

 

 

  • 서버의 clientSocket과 client의 socket이 1:1로 매칭이 되어야 함
  • 통신이 되려면 서버의 clientSocket도 Stream을 만들어야 된다.
  • 이렇게 하면 일단 1:1은 가능

 

ServerThread - client와 1:1로 대화하는 클래스

 

  • ServerFrame의 UI를 가져다가 써야하니까 ServerFrame을 생성자로 가져옴

 

 

  • ChatData에서 Write했던 Object를 readObject
  • ChatData에서 미리 설정해뒀던 final 상수값을 가져다가 쓴다
  • case 1 (로그인정보) 라고 해도 되지만, 따로 설명으로 주석달아야하는 번거로움 줄이기 위해 상수값으로 미리 정해서 쓰기

(command는 그냥 int 변수인데, 1이면 로그인, 2면 로그아웃 등 Action 에 번호를 부여함)

  • 메시지를 textPane에 뿌려주면 되는데 textPane에 HTML kit로 씌웠기 때문에 frame.kit 로 메시지 뿌려줄 수 있음

 

→ Serverframe

  • accept가 되는 순간 thread 시작
  • 클라이언트 입장에서는 소켓 생성하는 순간 자기자신의 정보를 주고 write Object하면 readObject가 그 데이터를 받아서 화면에 뿌려줌

 

메시지 전송 작업

메시지 텍스트필드 - keyReleased - send 메소드 실행 (엔터키 칠때 전송)

전송버튼 - Actionperformed - 마찬가지로 send 메소드 실행

 

 

send 메소드

  • try - catch는 문법적으로 무조건
  • 전송할때 중요한 정보 : mId, command는 메시지, msg 는 그 내용

 

 

 

 

 

 

Notion2Tistory

 

boltlessengineer.github.io

이것이 자바다 (신용권의 Java 프로그래밍 정복)

 

이것이 자바다

『이것이 자바다』은 15년 이상 자바 언어를 교육해온 자바 전문강사의 노하우를 아낌 없이 담아낸 자바 입문서이다. 자바 입문자를 배려한 친절한 설명과 배려로 1장에 풀인원 설치 방법을 제

book.naver.com