반응형
JSP 주석은 JSP 페이지 내에서 주석을 작성할 때 사용됩니다. 주석은 JSP 페이지를 해석할 때 무시되며, 최종 HTML 페이지에 포함되지 않습니다. JSP에는 HTML 주석, JSP 주석, 그리고 Java 주석이 있습니다.

 

HTML 주석

HTML 주석은 최종 HTML 페이지에 포함되며, 브라우저에서 볼 수 있습니다.

 

<!-- 이것은 HTML 주석입니다. 최종 HTML 페이지에 포함됩니다. -->

 

JSP 주석

JSP 주석은 JSP 페이지를 해석할 때 무시되며, 최종 HTML 페이지에 포함되지 않습니다.
<%-- 이것은 JSP 주석입니다. 최종 HTML 페이지에 포함되지 않습니다. --%>

 

Java 주석

Java 주석은 스크립트릿, 선언, 표현식 등 Java 코드 내부에서 사용됩니다.
<% 
    // 이것은 한 줄짜리 Java 주석입니다.
    /* 이것은 여러 줄짜리 
       Java 주석입니다. */
%>

 

JSP 지시자

페이지 지시자는 JSP 페이지의 전체 설정을 지정합니다. 예를 들어, 페이지의 인코딩, import 문, 에러 페이지 등을 설정할 수 있습니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page errorPage="error.jsp" %>

 

include 지시자

include 지시자는 다른 JSP 파일을 현재 JSP 파일에 포함시킵니다. 이는 정적 포함 방식으로, 컴파일 시 포함됩니다.
<%@ include file="header.jsp" %>

 

코드 실습 1 - 주석을 사용해 보자
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <title>JSP 주석 예제</title>
</head>
<body>
    <!-- HTML 주석: 이것은 최종 HTML 페이지에 포함됩니다. -->
    <%-- JSP 주석: 이것은 최종 HTML 페이지에 포함되지 않습니다. --%>
    <%
        // Java 주석: 한 줄짜리 주석
        /* Java 주석: 
           여러 줄짜리 주석 */
    %>
    <h1>JSP 주석 예제</h1>
</body>
</html>

 

코드 실습 2 - JSP 지시자와 include 의 사용

header.jsp

header.jsp 파일에는 페이지의 헤더 부분을 포함합니다. 이 파일에는 <html>, <head>, <body> 태그를 열고, 공통으로 사용되는 스타일시트나 스크립트를 포함할 수 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공통 헤서 만들어보기</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
	<header>
		<h1>사이트 이름</h1>
		<nav>
			<ul>
				<li><a href="home.jsp">홈</a></li>
				<li><a href="about.jsp">소개</a></li>
				<li><a href="contact.jsp">연락처</a></li>
			</ul>
		</nav>
	</header>

home.jsp

home.jsp 파일에서는 header.jsp와 footer.jsp 파일을 포함하여 페이지의 본문 내용을 작성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<%@ page import="java.util.Date" %>

<h1>JSP 지시자 예제</h1>
<p> 현재 시간 <%= new Date() %> </p>

<%@ include file="footer.jsp" %>

 

footer.jsp

footer.jsp 파일에는 페이지의 푸터 부분을 포함합니다. 이 파일에서는 열린 <body>와 <html> 태그를 닫습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

		<footer>
			<p>공통 푸터 &copy; 2024</p>
		</footer>    

	</body>
</html>
반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] JSP 기초 문법  (0) 2024.07.03
[JSP] JSP 라이프사이클  (0) 2024.07.03
[JSP] Java Server Pages 란?  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02
반응형

JSP는 기본적으로 HTML 문서 안에 자바 언어를 삽입해 사용할 수 있도록 설계 되어 있습니다.

그래서 실제로 대부분의 변수 선언, 메서드 선언, 로직 등은 자바 언어로 작성할 수 있습니다.

하지만 HTML 사이에 자바 코드를 끼워 넣을 때 필요한 문법이 몇 가지 있습니다.

💡 JSP 기초 문법의 종류
- JSP 지시어, Directive
- 스크립트릿(Scriptlet)
- 선언부(Declaration)
- 표현부(Expession)
- JSP 액션 태그

 

JSP 지시어, Directive
<%@ xxxx…. %>
JSP 디렉티브는 JSP 페이지의 전반적인 속성을 설정합니다. 주로 페이지 속성, import 등을 지정합니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page import="java.lang.Math" %>

 

스크립트릿(Scriptlet)
Java 코드를 HTML 중간에 삽입할 때 사용한다.
<% ... %> 태그 사이에 Java 코드를 작성한다 (코드 실행 영역에 해당)

 

<% 
    String greeting = "Hello, JSP!";
    out.println(greeting);
%>

 

선언부(Declaration)
JSP 페이지에서 변수를 선언하거나 메서드를 정의할 때 사용한다.
<%! ... %> 태그를 사용한다.

 

<%! 
    private String greeting = "Hello, JSP!";
    
    public String getGreeting() {
        return greeting;
    }
%>

 

표현식(Expression)
값을 출력할 때 사용하며, Java 표현식을 평가한 결과를 HTML로 출력한다.
<%= ... %> 태그를 사용한다.
<%
    String greeting = "Hello, 길동!";
%>
<p>Greeting: <%= greeting %></p>

 

JSP 액션 태그(Action Tags)
JSP 페이지에서 자바빈즈(Beans)를 사용하거나 다른 JSP 페이지를 포함시키는 등의 작업을 수행할 때 사용됩니다.

 

// 자바빈즈를 생성하거나 찾을 때 사용합니다.
<jsp:useBean id="myBean" class="com.example.MyBean" scope="session" />

// 자바빈즈의 속성 값을 설정할 때 사용합니다.
<jsp:setProperty name="myBean" property="username" value="JohnDoe" />

// 자바빈즈의 속성 값을 가져올 때 사용합니다.
<p>Username: <jsp:getProperty name="myBean" property="username" /></p>

// 다른 JSP 페이지를 포함시킬 때 사용합니다. 
<jsp:include page="header.jsp" />

// 다른 JSP 페이지로 요청을 포워드할 때 사용합니다.
<jsp:forward page="nextPage.jsp" />

... 등

 

💡 자바빈즈(JavaBeans)란?

재사용 가능한 객체: 자바빈즈는 재사용 가능하도록 설계된 Java 객체입니다.
특정 규약이 적용된 객체: 자바빈즈는 캡슐화, 기본 생성자, 직렬화 등의 규약을 따릅니다.
캡슐화(Encapsulation): 필드는 private으로 선언하고, 접근자 메서드(getter)와 설정자 메서드(setter)를 통해 접근합니다.
기본 생성자(Default Constructor): 자바빈즈 클래스는 기본 생성자를 반드시 가져야 합니다.
직렬화(Serialization): 자바빈즈는 Serializable 인터페이스를 구현하여 직렬화할 수 있습니다.
데이터 저장, 연산 및 전송: 자바빈즈는 애플리케이션에서 데이터를 저장하고, 연산을 수행하며, 다른 컴포넌트나 시스템으로 데이터를 전송하는 데 도움을 줍니다.

정리 - 동일한 클래스를 여러 곳에서 인스턴스화 해서 사용가능하며 스코프(scope) 내에서 재사용될 수 있습니다. 세션 스코프(scope)에서 생성된 자바빈즈 객체는 세션 내내 동일한 객체로 유지될 수 있습니다.

자바빈즈와 스코프

page: 현재 페이지에서만 사용 가능 (기본값)
request: 하나의 요청 동안 사용 가능
session: 세션 동안 사용 가능
application: 애플리케이션 전체에서 사용 가능

 

코드 실습 1 - 인사말 생성기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<h1>인사말 생성기</h1>
	<!-- 절대 경로 -->
	<!-- 상대 경로 -->
	<form action="greet.jsp" method="POST">
		<label for="name">당신에 이름을 입력하세요: </label>
		<input type="text" id="name" name="name" >
		<button type="submit">서버로 제출</button>
	</form>
	
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!-- JSP 페이지의 설정을 정의하는 지시자   -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>인사말을 완성 하였습니다.</h1>
	
	<%
		// 자바 실행 코드 
		// request 객체에서 값 추출 
		String name = request.getParameter("name");
		if(name == null || name.trim().isEmpty()) {
			out.println("<p> 앗! 당신에 이름을 먼저 입력해주세요 </p>");
		} else {
			out.print("<p>반가워, " + name + "! 나의 JSP Site 잘 왔어 환영~~");
		}
	%>
	
	<!-- 다시 이전 페이지로( 특정 페이지로 이동)   -->
	<a href="greet_from_page.html">Back</a>
	

</body>
</html>

 

코드 실습 2 - 간단한 계산기
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            display: flex;
            height: 100vh;
            justify-content: center;
            align-items: center;
            margin: 0;
            background-color: #f0f0f0;
        }
        .container{
            width: 300px;
            background-color: #fff;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        form{
            display: flex;
            flex-direction: column;
        }
        label{
            margin-bottom: 10px;
        }

        input[type="number"] {
            height: 30px;
            border: 1px solid #bababa;
            border-radius: 5px;
            margin-bottom: 20px;
        }
        input[type="submit"] {
                height: 40px;
                border-radius: 5px;
                border: 0;
                background-color: #45a049;
                color: #fff;
        }
        input[type="submit"]:hover{
            background-color: #1c5a1f;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>간단한 계산기</h1>
        <form action="calculator.jsp" method="post">
            <label for = "num1">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num1" name="num1" required="required">

            <label for = "num2">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num2" name="num2" required="required">

            <input type="submit" value="계산 요청하기">
        </form>
    </div>
</body>
</html>

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            display: flex;
            height: 100vh;
            justify-content: center;
            align-items: center;
            margin: 0;
            background-color: #f0f0f0;
        }
        .container{
            width: 300px;
            background-color: #fff;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        form{
            display: flex;
            flex-direction: column;
        }
        label{
            margin-bottom: 10px;
        }

        input[type="number"] {
            height: 30px;
            border: 1px solid #bababa;
            border-radius: 5px;
            margin-bottom: 20px;
        }
        input[type="submit"] {
                height: 40px;
                border-radius: 5px;
                border: 0;
                background-color: #45a049;
                color: #fff;
        }
        input[type="submit"]:hover{
            background-color: #1c5a1f;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>간단한 계산기</h1>
        <form action="calculate.jsp" method="post">
            <label for = "num1">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num1" name="num1" required="required" value="10">
            
            <label for = "num2">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num2" name="num2" required="required" value="20">
            <input type="submit" value="계산 요청하기">
        </form>
    </div>
</body>
</html>
반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] 주석과 지시자  (0) 2024.07.03
[JSP] JSP 라이프사이클  (0) 2024.07.03
[JSP] Java Server Pages 란?  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02
반응형

1. JSP 라이프사이클이란?

JSP 라이프사이클은 JSP 페이지가 요청을 처리하기 위해 거치는 일련의 단계를 의미합니다. JSP 페이지는 서블릿으로 변환되고, 컴파일되고, 요청을 처리한 후, 소멸되는 과정을 거칩니다. 즉, 라이프사이클은 JSP의 생성으로 시작하여 JSP의 해체로 끝납니다.

 

1. JSP 페이지 번역 (Translation) 
   └── example.jsp -> example_jsp.java
-- JSP 컨테이너는 JSP 파일을 서블릿 자바 파일로 변환합니다.

2. JSP 페이지 컴파일 (Compilation)
   └── example_jsp.java -> example_jsp.class
-- 서블릿 자바 파일을 컴파일하여 자바 바이트코드로 변환합니다.

3. 클래스 로딩 (Class Loading)
   └── example_jsp.class 로드
-- 컴파일된 클래스 파일을 JVM으로 로드합니다.  

4. 인스턴스화 (Instantiation)
   └── new example_jsp()
-- 서블릿 클래스의 객체를 생성합니다.

5. 초기화 (Initialization)
   └── example_jsp._jspInit()
-- 서블릿 객체의 초기화 작업을 수행합니다.

6. 요청 처리 (Request Processing)
   └── example_jsp._jspService(request, response) 
-- 라이언트의 요청을 처리하고 응답을 생성합니다.

7. 소멸 (Destroy)
   └── example_jsp._jspDestroy()
-- 서블릿 객체가 소멸될 때 자원을 해제합니다.

 

WAS (웹 애플리케이션 서버)
│
├── 웹 컨테이너 (Web Container)
│   │
│   ├── 서블릿 컨테이너 (Servlet Container)
│   │   ├── 서블릿 클래스 로딩
│   │   ├── 서블릿 인스턴스 생성
│   │   ├── 서블릿 초기화 (init)
│   │   ├── 요청 처리 (service, doGet, doPost)
│   │   └── 서블릿 소멸 (destroy)
│   │
│   └── JSP 컨테이너 (JSP Container)
│       ├── JSP 페이지 번역 (Translation)
│       ├── JSP 페이지 컴파일 (Compilation)
│       ├── 클래스 로딩 (Class Loading)
│       ├── 인스턴스화 (Instantiation)
│       ├── 초기화 (jspInit)
│       ├── 요청 처리 (jspService)
│       └── 소멸 (jspDestroy)
│
│
└── ...

 

샘플 코드
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>    
<%
	// http://localhost:8080/jsp/example.jsp
	// 초기화 단계(jspInit 역할)
	if(application.getAttribute("initialized") == null) {
		application.setAttribute("initialized", true);
		application.setAttribute("initializedTime", new Date());
		out.println("JSP가 초기화 되었습니다. <br>");
	}
	
	out.println("요청이 완료 되었습니다. <br>");
	out.println("현재 시간 : " + new Date() + " <br>");
	
	// 세션이라는 전역 메모리지에 데이터를 저장하고 확인해 보자. 
	String message = (String)session.getAttribute("message");
	if(message != null) {
		out.println("세션 메시지 : " + message);
	} else {
		out.println("저장된 세션 메시지가 없습니다.");
	}
	
	// 세션이라는 메모리에 key, value 를 할당하자. 
	session.setAttribute("message", "안녕~ 세션에 저장한 메세지야");
	
%>
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<h1>JSP 라이프 사이클 확인</h1>
	<p>이 페이지에 학습 목적은 JSP 동작 방식에 대한 이해와 라이프 사이클 입니다.</p>

</body>
</html>

<%
	// 소멸 단계 확인 (jspDestroy)
	if(application.getAttribute("initialized") != null) {
		application.removeAttribute("initialized");
		application.removeAttribute("initializedTime");
		out.println("JSP 객체가(서블릿) 소멸 되었습니다. <br>");
	}
%>

반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] 주석과 지시자  (0) 2024.07.03
[JSP] JSP 기초 문법  (0) 2024.07.03
[JSP] Java Server Pages 란?  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02
반응형
1. JSP의 정의와 역할을 이해한다.
2. JSP의 장점과 특징을 파악한다.
3. JSP와 관련된 기본 용어를 익힌다.

 

1. JSP란 뭘까?

Java Server Pages (JSP)는 동적인 웹 콘텐츠를 생성하기 위한 서버 측 기술이다. JSP는 HTML 페이지 내에 Java 코드를 포함시켜 웹 서버에서 실행된 후, 클라이언트에 HTML을 전송하는 방식으로 동작한다. 좀 더 자세히 말하자면 JSP(Java Server Pages)는 자바 서버 페이지의 약자로, 웹 애플리케이션 개발을 위한 서버 사이드 기술(Server-Side Rendering)입니다. JSP는 HTML, CSS, JavaScript 등의 클라이언트 사이드 언어와 함께 사용되어 동적인 웹 페이지를 생성하는 데 사용됩니다. 자바 코드를 HTML 코드에 삽입하여 웹 서버에서 실행할 수 있게 해주며, 그 결과는 클라이언트의 웹 브라우저로 전송됩니다.

 

SSR은 Server-Side Rendering(서버 측 렌더링)의 약어입니다. SSR은 클라이언트에게 웹 페이지를 제공하기 전에 서버에서 웹 페이지를 렌더링하여 HTML을 생성하는 웹 개발 방법론입니다. 이 방법론은 클라이언트에게 정적인 HTML을 먼저 제공하고, 클라이언트 측에서 JavaScript를 사용하여 동적인 콘텐츠를 추가하는 방식인 Client-Side Rendering(CSR)대비됩니다.

 

 

2. Servlet vs JSP

JSP 역할

웹 애플리케이션에서 사용자 요청을 처리하고, 동적으로 생성된 HTML을 클라이언트에게 반환한다. 프론트엔드와 백엔드의 중간 역할을 하며, HTML과 같은 프론트엔드 코드와 Java와 같은 백엔드 코드를 혼합하여 사용할 수 있다.

 

JSP의 기본 동작 원리

클라이언트 요청: 클라이언트(웹 브라우저)가 JSP 페이지에 접근한다.

서버 처리: 웹 서버(아파치 톰캣)가 JSP 페이지를 찾아 Java 서블릿으로 변환한 후 컴파일하여 실행한다.

응답 생성: JSP 페이지가 실행되어 동적인 HTML을 생성하고, 이를 클라이언트에게 전송한다.

 

샘플 코드 확인 1
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<html>
<head>
    <title>My First JSP Page</title>
</head>
<body>
    <h1>Hello, JSP!</h1>
    <%
        String message = "Welcome to Java Server Pages!";
        out.println("<p>" + message + "</p>");
    %>
</body>
</html>

 

샘플 코드 확인 2
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>JSP Example</title>
</head>
<body>
    <h1>JSP Example</h1>
    
    <hr>
    
    <%-- JSP 디렉티브 : 페이지 속성 설정 --%>
    <%@ page import="java.util.Date" %>
    <%@ page import="java.text.SimpleDateFormat" %>
    
    <%-- JSP 스크립트릿 : Java 코드 영역 --%>
    <%
        // 현재 날짜와 시간을 가져오기
        Date now = new Date();
        
        // 날짜 포맷 지정
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDate = sdf.format(now);
    %>
    
    <%-- HTML과 함께 JSP 표현식 사용하여 날짜 출력 --%>
    <p>현재 시간: <%= formattedDate %></p>
    
    <%-- JSP 선언문 : 변수 선언 --%>
    <%!
        int number = 10;
        String message = "Hello, JSP!";
    %>
    
    <%-- HTML과 함께 JSP 표현식 사용하여 변수 출력 --%>
    <p>숫자: <%= number %></p>
    <p>메시지: <%= message %></p>
    
    <%-- JSP 주석 : HTML 주석 --%>
    <!-- 이 부분은 HTML 주석입니다. JSP에서는 이렇게 사용할 수 있습니다. -->
    
    <%-- JSP 액션 태그 : Java 코드 실행 및 제어 --%>
    <%-- if-else 구문 --%>
    <% if (number > 5) { %>
        <p>숫자가 5보다 큽니다.</p>
    <% } else { %>
        <p>숫자가 5보다 작거나 같습니다.</p>
    <% } %>
    
     <%-- JSP 액션 태그 : include 지시자를 사용한 다른 JSP 파일 포함 --%>
    <%-- <%@ include file="included.jsp" %> -->
    
    
    <%-- JSP 표현언어(EL) : 변수 값 출력 --%>
    <p>EL 표현식을 사용한 숫자: ${10}</p>
    <p>EL 표현식을 사용한 메시지: ${"Hello, JSP!"}</p>
</body>
</html>

 

JSP 처리 과정

웹 브라우저에 JSP 페이지에 해당하는 URL을 입력하면, 톰캣 서버는 다음과 같은 과정을 거쳐 JSP 페이지를 실행한다.

 

JSP를 실행한다는 말은 곧 JSP 페이지를 컴파일한 결과인 서블릿 클래스를 실행한다는 의미가 된다.
반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] JSP 기초 문법  (0) 2024.07.03
[JSP] JSP 라이프사이클  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02
람다 함수  (0) 2023.10.02
반응형

❓ 스레드(Thread)란 무엇일까?

동작하고 있는 프로그램을 프로세스(Process)라고 합니다. 보통 1개의 프로세스는 한 가지의 일을 하지만, 스레드(thread)를 이용하면 한 프로세스 내에서 두 가지 또는 그 이상의 일을 동시에 할 수 있습니다.

*         프로세스  : 실행중인 프로그램
*         쓰레드   : 프로세스 안에 여러가지 작업들을 의미, 동시 실행 가능(병렬처리)
*         생성방법 ) 1) 인터페이스 상속 이용
*                    2) 부모 클래스 상속 이용

간단한 예제를 통해 스레드를 구현해보겠습니다.

 

💡 Runnable 인터페이스 상속을 이용한 스레드 구현

public class BeepTask implements Runnable{
    // TODO : 메서드 구현
    //  쓰레드 작업을 실행시키는 함수
    @Override
    public void run() {
        // TODO : 예제 : 삐소리를 들려 주는 코딩
        //  멀티미디어 객체 가져오기
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        for (int i = 0; i < 5; i++) {
            toolkit.beep(); // 컴퓨터 삐소리
            try {
                // 공유 함수
                Thread.sleep(500); // 0.5초 지연 후 삐 소리
            } catch (Exception e) {

            }
        }
    }
}

위의 예제는 스레드 작업 실행 시 윈도우 사운드인 비프음을 들려주는 코드입니다.

 

뒤에서 나올 예제에서 스레드 객체를 만들 때 스레드 클래스를 상속하여 만들기도 하지만 주로 Runnable 인터페이스를 사용합니다.

 

왜냐하면 스레드 클래스를 상속하면 스레드 클래스를 상속한 클래스가 다른 클래스를 상속할 수 없기 때문입니다.

 

위의 BeepTask 클래스는 Runnable 인터페이스를 사용하였습니다.

 

* description : 작업쓰레드 #1 : 삐소리
*               main 함수 : 메인 쓰레드 : 화면출력 : 띵 글자 5번 출력
*               동시 실행
public class BeepTaskApplication {
    public static void main(String[] args) {
//        TODO : 1) 작업쓰레드 객체 생성
        Runnable runnable = new BeepTask(); // 다형성
//        TODO : 2) 쓰레드 생성자의 매개변수로 전달
        Thread thread = new Thread(runnable);
//        TODO : 3) 작업쓰레드 # 1 : 삐소리 실행(run() 실행됨)
        thread.start();

//        TODO : 4) 메인쓰레드 : 화면에 띵 글자 출력
        for (int i = 0; i < 5; i++) {
            System.out.println("띵");
            try {
                Thread.sleep(500); // 0.5 지연
            } catch (Exception e){}
        }
    }
}

위의 BeepTaskApplication 클래스는 실행함수입니다.

 

메인 함수에서 다형성을 이용해 runnable 형태의 BeepTask 객체를 생성해주고,

 

스레드의 생성자(thread)의 매개변수로 runnable를 전달해줍니다.

 

그리고 작업스레드 #1을 실행하는 start함수를 이용해 실행시킵니다.

 

그리고 화면에 출력하기 위해 for 반복문을 사용하여 화면에 출력합니다. 여기서 예외처리를 통해 sleep 함수를 사용해 0.5초 지연을 시켜줍니다.

 

실행결과는 다음과 같습니다.

0.5초씩 지연되며 윈도우 비프음이 실행되며 '띵'이라는 글자가 출력됩니다.





 

💡 Thread 클래스를 상속받아 스레드 구현

다음은 thread 클래스를 상속받아 스레드를 구현해보겠습니다.

public class BeepThread extends Thread{
//    TODO : 쓰레드 작업을 실행시키는 함수
    @Override
    public void run() {
//         TODO: beep 를 들려주는 코드
//            자바쪽 멀티미디어 객체 : 소리, 그림, 이미지 등등 다루는 객체
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        for (int i = 0; i < 5; i++) {
            toolkit.beep(); // 삐소리
            try {
                Thread.sleep(500); // 0.5 삐소리 지연
            } catch (Exception e) {}
        }
    }
}

위의 BeepThread 클래스는 Thread 클래스를 상속받은 형태입니다.

 

run() 함수는 부모 클래스인 Thread 클래스의 run() 함수를 오버라이딩 하였습니다.

 

여기서 Toolkit은 JAVA 멀티미디어를 다루는 객체를 말합니다.

 

아래에 반복문을 통해 toolkit의 함수인 beep() 를 사용하여 윈도우 비프음을 실행시키고

 

예외처리를 통해 0.5초 지연을 해줍니다.

 

public class BeepThreadApplication {
    public static void main(String[] args) {
//        TODO : 1) 쓰레드 객체 생성
        Thread thread = new BeepThread();   // 다형성
//        TODO : 2) 쓰레드 실행 #1 : 내부적으로 run() 함수가 실행됨
        thread.start();
//        TODO : 3) main 쓰레드 작업 #2 : 화면 출력 (띵 * 5 출력)
        for (int i = 0; i < 5; i++) {
            System.out.println("띵");
            try {
                Thread.sleep(500); // 0.5초 지연
            }catch (Exception e){}
        }
    }
}

위의 코드는 상속받은 스레드를 실행하는 클래스입니다.

 

먼저 메인 함수에서 스레드 객체를 생성해주고,

 

스레드 #1를 실행합니다.

 

그리고 for 반복문을 통해 화면에 출력해줍니다.

 

실행결과는 다음과 같습니다.

띵 // 윈도우 비프음과 동시에 실행됨

띵 // 윈도우 비프음과 동시에 실행됨

띵 // 윈도우 비프음과 동시에 실행됨

띵 // 윈도우 비프음과 동시에 실행됨

띵 // 윈도우 비프음과 동시에 실행됨

 


💡 요약

Thread 객체의 생성자로 Runnable 인터페이스를 구현한 객체를 전달하는 방법을 사용하면 Thread 클래스를 상속받아 구현한 것과 동일하게 작동합니다.

thread 객체가 Thread 클래스를 상속했을 경우에는 다른 클래스를 상속받을 수 없지만, 인터페이스를 사용한 경우에는 다른 클래스 상속이 가능하므로 좀 더 유연한 프로그램으로 만들 수 있습니다.


📖 Reference

반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] JSP 라이프사이클  (0) 2024.07.03
[JSP] Java Server Pages 란?  (0) 2024.07.03
중첩 클래스  (0) 2023.10.02
람다 함수  (0) 2023.10.02
파일 클래스를 이용한 파일 출력  (0) 2023.10.02
반응형

중첩 클래스 정의

* description : 특수클래스 -> 중첩 클래스 : 클래스안에 클래스
* 요약 :
* 클래스의 3요소 : 속성, 생성자, 함수
* 멤버 클래스 - 일반 속성 클래스 : 외부 클래스를 생성해야 내부 클래스를 사용가능
*             정적 속성 클래스 : 외부 클래스 생성없이 바로 사용 가능
* 로컬 클래스 - 함수(메소드) 안의 클래스 : 함수를 실행해야 사용 가능
public class Outer {
    // TODO : 클래스의 3요소 = 속성, 생성자, 함수
    // 생성자
    public Outer() {
        System.out.println("외부 클래스가 생성됨");
    }

    // TODO : 일반 속성 (내부)클래스
    public class Attr {
        //        생성자
        public Attr() {
            System.out.println("Attr 내부 클래스가 생성됨");
        }

        int field1;     // 속성

        void method1() {
        }
    }

    // TODO : 정적 속성(내부) 클래스
    static class Share {
        // 생성자
        public Share() {
            System.out.println("Share 정적 객체가 생성됨");
        }
        int filed1; // 일반 속성
        static int field2; // 정적 속성
        void method1(){};   // 일반 함수
        static void method2(){
            System.out.println("정작함수가 실행됨");
        };   // 정적 함수
    }
    
    // TODO : 로컬 클래스 : 함수 안의 클래스
    void method(){
        // TODO : 내부 클래스
        class Local{
            // 생성자
            public Local() {
                System.out.println("Local 객체가 생성됨");
            }
            int field1; // 속성
            void method1(){};   // 함수
        }
        // Local 객체 생성
        Local local = new Local();
        local.field1 = 3;       // 내부클래스 속성
        local.method1();        // 내부클래스 함수
    }
}

중첩클래스의 사용

public class OuterApplication {
    public static void main(String[] args) {
//        TODO : 외부클래스 : Outer 객체 생성
        Outer outer = new Outer();

//        TODO : 1) 일반 속성 내부 클래스 객체 생성
//         사용법 : 외부클래스.내부클래스 객체변수 = 외부객체.new 내부생성자함수();
        Outer.Attr attr = outer.new Attr();
        attr.field1 = 3;    // 내부 클래스의 속성
        attr.method1();     // 내부 클래스의 함수

//        TODO : 2) 정적(공유) 속성 내부 클래스 객체 생성 없음 : 바로 호출
//         사용법 : 외부클래스.내부클래스.속성, 외부클래스.내부클래스.함수()
        Outer.Share.field2 = 3;     // 공유 내부 클래스의 공유속성 호출
        Outer.Share.method2();      // 공유 내부 클래스의 공유함수 호출

//        TODO : 3) 로컬 클래스 : 함수 안의 클래스
        outer.method(); // 안에서 클래스 자동 생성됨



    }
}

실행결과

 

외부 클래스가 생성됨
Attr 내부 클래스가 생성됨
정작함수가 실행됨
Local 객체가 생성됨

반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] Java Server Pages 란?  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
람다 함수  (0) 2023.10.02
파일 클래스를 이용한 파일 출력  (0) 2023.10.02
objectstream  (0) 2023.10.02
반응형
//         js   : 함수의 매개변수로 함수를 넣을 수 있음, 리턴값도 함수 내보내기 가능
//         java : 함수의 매개변수/리턴값으로 함수 사용 금지
//           => 부가기능 추가 : 5가지 경우의 대표 함수(형태)를 만들어서 사용
//           Runnable(실행) 함수   : 매개변수(x), 리턴값(x) 함수  예) void run()
//           Supplier(공급자) 함수 : 매개변수(x), 리턴값(o) 함수  예) int get()
//           Consumer(소비자) 함수 : 매개변수(o), 리턴값(x) 함수  예) void accept(int t)
//           Function(일반) 함수  : 매개변수(o), 리턴값(o) 함수  예) int apply(int t)
//           Predicate(논리(명제)) 함수  : 매개변수(o), 리턴값(o, 참/거짓) 함수  예) boolean apply(int t)
 /**
     * 1~100까지 중 10개의 랜덤 숫자 배열에 넣기 함수
     * 제네릭 함수 : 제네릭을 매개변수에 사용하는 함수, 반환타입 앞에 <T>를 붙임
     * T 클래스 : 대표 T : 임의의 어떤 클래스를 대표하는 클래스로 사용
     * 제네릭 함수 : static <T> 반환타입 함수명(매개변수타입 매개변수명...) {}
     *
     * @param s
     * @param list
     * @param <T>
     */
    static <T> void makeRandomList(Supplier<T> s, List<T> list) {
        for (int i = 0; i < 10; i++) {
            list.add(s.get()); // s.get() : 매개변수로 전달되는 생산자 함수를 대리하는 함수
        }
    }

    /**
     * List에 저장된 요소의 값이(i) 짝수인것만 화면에 출력
     *
     * @param p
     * @param c
     * @param list
     * @param <T>
     */
    static <T> void printEventNum(Predicate<T> p, Consumer<T> c, List<T> list) {
        for (T i : list) {
//            명제 : 참/거짓이 있는 문장
            if (p.test(i)) { //  p.test(값)   : 매개변수로 전달되는 논리(명제) 함수를 대리하는 함수
                c.accept(i); // c.accept(값) : 매개변수로 전달되는 소비자 함수를 대리하는 함수
            }
        }
        System.out.println(); // 줄바꿈
    }

    /**
     * 1의 자리를 없앤 새로운 배열을 만들어서 List에 저장하는 함수(1의 자리는 0으로 변경)
     * 제네릭 함수 : 함수의 리턴값 앞에 <T>, 제네릭표현식을 사용하는 함수
     *
     * @param f
     * @param list
     * @param <T>
     * @return
     */
    static <T> List<T> doSomething(Function<T, T> f, List<T> list) {
        List<T> newList = new ArrayList<T>(list.size());

        for (T i : list) {
            newList.add(f.apply(i)); //  p.apply(값)   : 매개변수로 전달되는 일반 함수를 대리하는 함수
        }
        return newList;
    }
 public static void main(String[] args) {

        Supplier<Integer> s = () -> (int)(Math.random()*100) + 1;   // 1 ~ 100까지 랜덤
        Consumer<Integer> c = i -> System.out.println(i + ",");     // i 출력 함수
        Predicate<Integer> p = i -> i % 2 == 0;                     // 2의 배수만 리턴하는 함수
        Function<Integer, Integer> f = i -> i/10*10;                // i의 값 중 1의 자리를 없애는 함수
                                                                    // 예) 9.7 -> 90

//        TODO : 결과 실행
        List<Integer> list = new ArrayList<>();

//        TODO : 정적 함수를 호출하면 마지막 매개변수(배열)에 값이 저장되어 리턴됨(화면출력됨)
        makeRandomList(s, list);
        System.out.println(list);   // 결과출력 : 1 ~ 100까지 랜덤수가 화면출력됨
        System.out.println("------------------------------------------------------");
        printEventNum(p, c, list);  // 결과 : 배열에 짝수인것만 화면에 출력
        System.out.println("------------------------------------------------------");
        List<Integer> list2 = doSomething(f, list);
        System.out.println(list2); // 결과 : 일의 자리를 없앤 배열



    }

 

실행 결과

[97, 38, 64, 5, 62, 76, 58, 49, 35, 29]
------------------------------------------------------
38,
64,
62,
76,
58,

------------------------------------------------------
[90, 30, 60, 0, 60, 70, 50, 40, 30, 20]

반응형

'Java > Java 이론' 카테고리의 다른 글

스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02
파일 클래스를 이용한 파일 출력  (0) 2023.10.02
objectstream  (0) 2023.10.02
printstream  (0) 2023.10.02
반응형
* description : File 클래스 : 파일생성 또는 폴더 생성, 정보 보기 기능
public class FileApplication {
    public static void main(String[] args) throws Exception {
//        TODO : 1) 텍스트 파일을 읽어서 리스트 배열로 가져오기 : Files.readAllLines(Paths.get(경로))
        List<String> lines
                = Files.readAllLines(Paths.get("src/main/resources/file1.txt"));
        System.out.println(lines);  // 배열 출력

//        TODO : 2) byte 파일을 읽어서 데이터 가져오기
        byte[] bytes = Files.readAllBytes(Paths.get("src/main/resources/test1.db"));
        System.out.println(Arrays.toString(bytes)); // 결과 출력

    }
}

 

실행결과


[hello, how are you, nice to meet you]
[10, 20, 30]

반응형

'Java > Java 이론' 카테고리의 다른 글

중첩 클래스  (0) 2023.10.02
람다 함수  (0) 2023.10.02
objectstream  (0) 2023.10.02
printstream  (0) 2023.10.02
보조스트림 : 기본 자료형으로 입출력하기  (0) 2023.10.02
반응형

객체 스트림을 사용하기 위해서 우선 객체 파일을 생성합니다.

package chap15.sec02.exam06;

import java.io.Serializable;
import java.util.Date;
import java.util.Objects;

/**
 * packageName : chap14.sec02.exam06
 * fileName : Board
 * author : ds
 * date : 2022-10-07
 * description : 게시판 객체
 * ===========================================================
 * DATE            AUTHOR             NOTE
 * —————————————————————————————
 * 2022-10-07         ds          최초 생성
 */
// 모델(Model) : 순수객체, 속성, 생성자, Setter/Getter, 그외에 로직을 구하는 함수는 없음
//    목적 : 데이터 저장용/검색용
// Service : 업무가 들어가 있는 클래스(객체)
// Controller : 여러 화면을(View) 조작하는(컨트롤하는) 클래스
//    MVC 디자인패턴(종합편) : M(Model) / V(View) / C(Controller)
public class Board implements Serializable {
//    속성
//    게시판 번호
    private int bno;
//    제목
    private String title;
//    내용
    private String content;
//    작성자
    private String writer;
//    날짜
    private Date date;

//    생성자
    public Board(int bno, String title, String content, String writer, Date date) {
        this.bno = bno;
        this.title = title;
        this.content = content;
        this.writer = writer;
        this.date = date;
    }

//    함수 재정의
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Board board = (Board) o;
        return bno == board.bno && Objects.equals(title, board.title) && Objects.equals(content, board.content) && Objects.equals(writer, board.writer) && Objects.equals(date, board.date);
    }

    @Override
    public int hashCode() {
        return Objects.hash(bno, title, content, writer, date);
    }

    @Override
    public String toString() {
        return "Board{" +
                "bno=" + bno +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", writer='" + writer + '\'' +
                ", date=" + date +
                '}';
    }
}

Serializable (직렬화)

 Object 또는 Data를 다른 컴퓨터의 자바 시스템에서도 사용 할수 있도록 바이트 스트림(stream of bytes) 형태로 연속전인(serial) 데이터로 변환하는 포맷 변환 기술을 일컫는다. 그 반대 개념인 역직렬화는(Deserialize)는 바이트로 변환된 데이터를 원래대로 자바 시스템의 Object 또는 Data로 변환하는 기술이다.

객체 클래스(위에서는 Borad)에 Serializable 을 상속받으면 가능

public class ObjectApplication {
    //    객체 쓰기 공유 함수
    public static void writeList() throws Exception {
//        자료구조 : ArrayList
        List<Board> list = new ArrayList<>(); // List 생성 (ArrayList)

        list.add(new Board(1, "제목1", "내용1", "글쓴이1", new Date()));
        list.add(new Board(2, "제목2", "내용2", "글쓴이2", new Date()));
        list.add(new Board(3, "제목3", "내용3", "글쓴이3", new Date()));

//        TODO: 객체를 파일에 쓰기(파일 생성)
        FileOutputStream fileOutputStream
                = new FileOutputStream("src/main/resources/board.txt");
//        TODO : 보조스트림 적용(객체 쓰기)
//              .writeObject(객체배열)
        ObjectOutputStream objectOutputStream
                = new ObjectOutputStream(fileOutputStream);

        objectOutputStream.writeObject(list);   // 객체 -> 파일 쓰기 함수 호출
        objectOutputStream.flush();
        objectOutputStream.close();

    }

    //    객체 읽기 공유 함수
    public static List<Board> readList() throws Exception {
//        TODO: 파일 읽기로 접근
        FileInputStream fileInputStream
                = new FileInputStream("src/main/resources/board.txt");

//        TODO : 보조스트림 적용 : 파일 -> 객체 읽기
        ObjectInputStream objectInputStream
                = new ObjectInputStream(fileInputStream);

//        TODO : 파일 -> 객체배열로 원복해서 읽기 : .readObject()
//            대상 객체[배열]은 Serializable 인터페이스를 상속받아야 함
        List<Board> list = (List<Board>)objectInputStream.readObject(); // 객체로 바꾸기(원복)
        return list;
    }

    public static void main(String[] args) throws Exception{
        writeList(); // 쓰기 공유 함수 객체배열 List 파일에 쓰기
//        파일에 쓴 것을 읽기
        List<Board> list = readList(); // 읽기 공유 함수(역직렬화)

        System.out.println(list);
    }
}

 

객체 쓰기 공유 함수

 //    객체 쓰기 공유 함수
    public static void writeList() throws Exception {
//        자료구조 : ArrayList
        List<Board> list = new ArrayList<>(); // List 생성 (ArrayList)

        list.add(new Board(1, "제목1", "내용1", "글쓴이1", new Date()));
        list.add(new Board(2, "제목2", "내용2", "글쓴이2", new Date()));
        list.add(new Board(3, "제목3", "내용3", "글쓴이3", new Date()));

//        TODO: 객체를 파일에 쓰기(파일 생성)
        FileOutputStream fileOutputStream
                = new FileOutputStream("src/main/resources/board.txt");
//        TODO : 보조스트림 적용(객체 쓰기)
//              .writeObject(객체배열)
        ObjectOutputStream objectOutputStream
                = new ObjectOutputStream(fileOutputStream);

        objectOutputStream.writeObject(list);   // 객체 -> 파일 쓰기 함수 호출
        objectOutputStream.flush();
        objectOutputStream.close();

    }

 

객체 읽기 공유 함수

//    객체 읽기 공유 함수
    public static List<Board> readList() throws Exception {
//        TODO: 파일 읽기로 접근
        FileInputStream fileInputStream
                = new FileInputStream("src/main/resources/board.txt");

//        TODO : 보조스트림 적용 : 파일 -> 객체 읽기
        ObjectInputStream objectInputStream
                = new ObjectInputStream(fileInputStream);

//        TODO : 파일 -> 객체배열로 원복해서 읽기 : .readObject()
//            대상 객체[배열]은 Serializable 인터페이스를 상속받아야 함
        List<Board> list = (List<Board>)objectInputStream.readObject(); // 객체로 바꾸기(원복)
        return list;
    }

 

메인 함수

 public static void main(String[] args) throws Exception{
        writeList(); // 쓰기 공유 함수 객체배열 List 파일에 쓰기
//        파일에 쓴 것을 읽기
        List<Board> list = readList(); // 읽기 공유 함수(역직렬화)

        System.out.println(list);
    }
}
반응형
반응형
public class PrintApplication {
    public static void main(String[] args) throws Exception {
        // TODO : 파일 쓰기용으로 생성
        FileOutputStream fileOutputStream
                = new FileOutputStream("src/main/resources/printstream.txt");

        // TODO : 보조스트림 적용 : print(), println() 함수가 있는 보조스트림
        PrintStream printStream =
                new PrintStream(fileOutputStream);

        // TODO : 파일에 한줄씩 내용쓰기
        printStream.println("프린터 보조 스트림");      // 줄바꿈 출력
        printStream.print("마치");                    // 줄바꿈 없음
        printStream.println("프린터가 출력되는 것처럼");
        printStream.println("파일에 작성합니다.");

        printStream.flush();    // 기본버퍼 -> 진짜파일에 쓰기
        printStream.close();    // 파일 닫기
    }
}

우선 기본 스트림인 파일 쓰기용 생성자를 생성합니다.

// TODO : 파일 쓰기용으로 생성
FileOutputStream fileOutputStream
        = new FileOutputStream("src/main/resources/printstream.txt");

 

보조스트림을 적용하여 기본스트림에 기능을 추가해줍니다.

// TODO : 보조스트림 적용 : print(), println() 함수가 있는 보조스트림
PrintStream printStream =
        new PrintStream(fileOutputStream);

 

함수를 사용하여 파일에 한줄씩 내용을 작성해줍니다.

// TODO : 파일에 한줄씩 내용쓰기
printStream.println("프린터 보조 스트림");      // 줄바꿈 출력
printStream.print("마치");                    // 줄바꿈 없음
printStream.println("프린터가 출력되는 것처럼");
printStream.println("파일에 작성합니다.");

 

마지막으로 기본버퍼에서 진짜파일에 쓰기 후 파일을 닫아줍니다.

printStream.flush();    // 기본버퍼 -> 진짜파일에 쓰기
printStream.close();    // 파일 닫기

 

결과

반응형
반응형

파일 쓰기

public class DataInputApplication {
    public static void main(String[] args) throws Exception {   // 예외처리
        // TODO : 파일 쓰기용으로 파일 생성
        FileOutputStream fileOutputStream
                = new FileOutputStream("src/main/resources/primitive.txt");

        // TODO : 보조스트림 : 기본 자료형 사용하게 만들어주는 스트림
        //      사용법 : new DataOutputStream(기본스트림);
        DataOutputStream dataOutputStream
                = new DataOutputStream(fileOutputStream);

        // 파일에 기본 자료형 쓰기 함수들
        // TODO : writeUTF("문자열") -> 파일에 문자열 쓰기
        //        writeDouble(실수) -> 파일에 실수 쓰기
        //        writeInt(정수) -> 파일에 정수 쓰기
        dataOutputStream.writeUTF("홍길동");
        dataOutputStream.writeDouble(95.4);
        dataOutputStream.writeInt(1);

//        TODO: 여기서 부터 코딩
        dataOutputStream.writeUTF("감자바");
        dataOutputStream.writeDouble(90.3);
        dataOutputStream.writeInt(2);
        
        // TODO : 파일 닫기
        dataOutputStream.flush();   // 기본버퍼의 내용을 진짜파일에 쓰기
        dataOutputStream.close();

    }
}

우선 FileOutputStream을 사용하여 파일을 생성합니다.

// TODO : 파일 쓰기용으로 파일 생성
FileOutputStream fileOutputStream
        = new FileOutputStream("src/main/resources/primitive.txt");

 

보조 스트림을 사용합니다.

// TODO : 보조스트림 : 기본 자료형 사용하게 만들어주는 스트림
//      사용법 : new DataOutputStream(기본스트림);
DataOutputStream dataOutputStream
        = new DataOutputStream(fileOutputStream);

dataOutputStream에는 여러 함수들이 존재합니다.

// TODO : writeUTF("문자열") -> 파일에 문자열 쓰기
//        writeDouble(실수) -> 파일에 실수 쓰기
//        writeInt(정수) -> 파일에 정수 쓰기
dataOutputStream.writeUTF("홍길동");
dataOutputStream.writeDouble(95.4);
dataOutputStream.writeInt(1);
dataOutputStream.writeUTF("감자바");
dataOutputStream.writeDouble(90.3);
dataOutputStream.writeInt(2);

마무리로 .flush()와 .close()를 실행합니다.

// TODO : 파일 닫기
dataOutputStream.flush();   // 기본버퍼의 내용을 진짜파일에 쓰기
dataOutputStream.close();

 

파일 읽기

생성한 파일을 읽기 위해 접근 생성자를 생성합니다.

FileInputStream fileInputStream
        = new FileInputStream("src/main/resources/primitive.txt");

 

보조스트림을 적용하여 기본자료형 기능을 추가해줍니다.

DataInputStream dataInputStream
        = new DataInputStream(fileInputStream);

 

반복문을 실행하여 화면에 출력합니다.

이때 반복문은 2번 실행합니다. 그 이유는 위에 요소를 2개 추가하였기 때문입니다.

        dataOutputStream.writeUTF("홍길동");
        dataOutputStream.writeDouble(95.4);
        dataOutputStream.writeInt(1);


        dataOutputStream.writeUTF("감자바");
        dataOutputStream.writeDouble(90.3);
        dataOutputStream.writeInt(2);

반복문을 작성할 때 주의점은 요소들의 바이트 크기가 각기 다르기 때문에 출력순서에 맞게 자료형을 읽어야 합니다.

        // TODO : 반복문 실행 후 화면에 출력 : 두번 실행
        //     주의점 : 바이트 크기가 각각 다르므로 출력순서에 맞게 자료형을 읽어야 함
        for (int i = 0; i < 2; i++) {
//            dataOutputStream.writeUTF("감자바"); //
//            dataOutputStream.writeDouble(90.3); // 8byte
//            dataOutputStream.writeInt(2);       // 4byte
            String name = dataInputStream.readUTF();        // 파일에서 읽기
            double score = dataInputStream.readDouble();        // 파일에서 읽기
            int order = dataInputStream.readInt();        // 파일에서 읽기
            System.out.println(name + ", " + score + ", " + order);

        }

마무리로 파일을 닫아줍니다.

// TODO : 파일 닫기
dataInputStream.close();
fileInputStream.close();

실행결과

홍길동, 95.4, 1
감자바, 90.3, 2

반응형

'Java > Java 이론' 카테고리의 다른 글

objectstream  (0) 2023.10.02
printstream  (0) 2023.10.02
파일 복사 성능 테스트(일반복사 vs 버퍼 사용복사)  (0) 2023.10.02
보조스트림  (0) 2023.09.27
입출력 Stream  (0) 2023.09.27
반응형

일반복사와 버퍼사용복사

public class BufferApplication {
    static int data = -1;

    // TODO : 정적(전역, 공유)함수 : 파일 copy 함수
    public static long copy(InputStream is, OutputStream os) throws Exception {     // 예외처리
        // 복사하는데 걸리는 시간 체크 : 시작시간 체크
        long start = System.nanoTime();

        // 복사 실행 코드
        while(true) {
            data = is.read();   // 읽기(원본)
            if(data == -1) break;   // 반복문 종료 조건, 파일의 끝 : -1 리턴
            os.write(data);     // 다른 파일에 쓰기(복사본)
        }

        // 종료 시간 체크
        long end = System.nanoTime();

        return (end - start);   // 걸린시간 리턴
    }

    public static void main(String[] args) throws Exception {
        // TODO : 원본 이미지 경로 지정
        String orgImgPath = "src/main/resources/images/boy.jpg";    // 일반복사 파일
        String orgImgPath2 = "src/main/resources/images/girl.jpg";  // 버퍼복사 파일

        // TODO : 복사본 이미지 경로 지정
        String cpyImgPath = "src/main/resources/images/boy_copy.jpg";   // 일반복사 파일
        String cpyImgPath2 = "src/main/resources/images/girl_copy.jpg"; // 버퍼복사 파일

        // FileInputStream 기본 스트림 중 1개
        // TODO : 파일 읽기용으로 원본 이미지 접근
        FileInputStream fileInputStream
                = new FileInputStream(orgImgPath);
        // TODO : 파일 쓰기용으로 복사본 이미지 생성
        FileOutputStream fileOutputStream
                = new FileOutputStream(cpyImgPath);

        // TODO : 복사함수(copy)를 이용해서 복사본 이미지 생성 + 소요시간 측정(리턴)
        long nonBufferTime = copy(fileInputStream, fileOutputStream);
        System.out.println("버퍼를 사용하지 않았을때 :" + nonBufferTime + "ns");

        fileInputStream.close();
        fileOutputStream.close();


    }
}

여기서 copy 함수는 파일을 복사하는데 걸리는 시간을 체크함과 동시에 복사를 실행하는 코드입니다.

public static long copy(InputStream is, OutputStream os) throws Exception {     // 예외처리
    // 복사하는데 걸리는 시간 체크 : 시작시간 체크
    long start = System.nanoTime();

    // 복사 실행 코드
    while(true) {
        data = is.read();   // 읽기(원본)
        if(data == -1) break;   // 반복문 종료 조건, 파일의 끝 : -1 리턴
        os.write(data);     // 다른 파일에 쓰기(복사본)
    }

    // 종료 시간 체크
    long end = System.nanoTime();

    return (end - start);   // 걸린시간 리턴
}

메인함수

public static void main(String[] args) throws Exception {
        // TODO : 원본 이미지 경로 지정
        String orgImgPath = "src/main/resources/images/boy.jpg";    // 일반복사 파일
        String orgImgPath2 = "src/main/resources/images/girl.jpg";  // 버퍼복사 파일

        // TODO : 복사본 이미지 경로 지정
        String cpyImgPath = "src/main/resources/images/boy_copy.jpg";   // 일반복사 파일
        String cpyImgPath2 = "src/main/resources/images/girl_copy.jpg"; // 버퍼복사 파일

        // FileInputStream 기본 스트림 중 1개
        // TODO : 파일 읽기용으로 원본 이미지 접근
        FileInputStream fileInputStream
                = new FileInputStream(orgImgPath);
        // TODO : 파일 쓰기용으로 복사본 이미지 생성
        FileOutputStream fileOutputStream
                = new FileOutputStream(cpyImgPath);

        // TODO : 복사함수(copy)를 이용해서 복사본 이미지 생성 + 소요시간 측정(리턴)
        long nonBufferTime = copy(fileInputStream, fileOutputStream);
        System.out.println("버퍼를 사용하지 않았을때 :" + nonBufferTime + "ns");

        fileInputStream.close();
        fileOutputStream.close();

//        ------------------- 버퍼 써서 파일 복사 ------------------

        // TODO : 파일 읽기용으로 원본 이미지 접근 : girl.jpg(이미지 경로 : orgImgPath2)
        FileInputStream fileInputStream2
                = new FileInputStream(orgImgPath2);
        // TODO : 파일 쓰기용으로 복사본 이미지 생성 (이미지 경로 : cpyImgPath2 )
        FileOutputStream fileOutputStream2
                = new FileOutputStream(cpyImgPath2);

        // TODO : 보조스트림(buffer) 적용 : new 보조스트림 생성자(기본스트림)
        BufferedInputStream bufferedInputStream
                = new BufferedInputStream(fileInputStream2);    // 읽기용(원본)
        BufferedOutputStream bufferedOutputStream
                = new BufferedOutputStream(fileOutputStream2);  // 쓰기용(복사본)

        // TODO : 복사(copy)와 함께 소요시간(리턴값) 체크
        long bufferTime = copy(bufferedInputStream, bufferedOutputStream);
        System.out.println("버퍼를 사용할때 : " + bufferTime + "ns");

        // TODO : 파일 닫기
        bufferedInputStream.close();
        bufferedOutputStream.close();

    }

먼저 일반 복사를 하기 위해 원본 이미지와 복사본 이미지의 경로를 지정해줍니다.

// TODO : 원본 이미지 경로 지정
String orgImgPath = "src/main/resources/images/boy.jpg";    // 일반복사 파일
String orgImgPath2 = "src/main/resources/images/girl.jpg";  // 버퍼복사 파일

// TODO : 복사본 이미지 경로 지정
String cpyImgPath = "src/main/resources/images/boy_copy.jpg";   // 일반복사 파일
String cpyImgPath2 = "src/main/resources/images/girl_copy.jpg"; // 버퍼복사 파일

 

FileInputStream 기본 스트림을 사용하여 읽기/쓰기용으로 생성자를 생성합니다.

// FileInputStream 기본 스트림 중 1개
// TODO : 파일 읽기용으로 원본 이미지 접근
FileInputStream fileInputStream
        = new FileInputStream(orgImgPath);
// TODO : 파일 쓰기용으로 복사본 이미지 생성
FileOutputStream fileOutputStream
        = new FileOutputStream(cpyImgPath);

메인함수 위에서 코딩하였던 복사함수를 이용하여 복사본 이미지를 생성하고 소요시간을 측정합니다.

// TODO : 복사함수(copy)를 이용해서 복사본 이미지 생성 + 소요시간 측정(리턴)
long nonBufferTime = copy(fileInputStream, fileOutputStream);
System.out.println("버퍼를 사용하지 않았을때 :" + nonBufferTime + "ns");

마무리로 파일을 닫아줍니다.

fileInputStream.close();
fileOutputStream.close();

일반 복사를 실행하였을 경우 실행속도는 다음과 같습니다.

버퍼를 사용하지 않았을때 :112719101ns

 

다음은 버퍼를 사용하여 파일을 복사해보겠습니다.

 

먼저 파일 읽기/쓰기용으로 이미지 접근, 복사본 이미지 생성 생성자를 코딩합니다.

// TODO : 파일 읽기용으로 원본 이미지 접근 : girl.jpg(이미지 경로 : orgImgPath2)
FileInputStream fileInputStream2
        = new FileInputStream(orgImgPath2);
// TODO : 파일 쓰기용으로 복사본 이미지 생성 (이미지 경로 : cpyImgPath2 )
FileOutputStream fileOutputStream2
        = new FileOutputStream(cpyImgPath2);

 

보조스트림을 적용합니다.

보조스트림 적용은 new 보조스트림 생성자안에 매개변수로 기본스트림을 넣어주는 형태입니다.

// TODO : 보조스트림(buffer) 적용 : new 보조스트림 생성자(기본스트림)
BufferedInputStream bufferedInputStream
        = new BufferedInputStream(fileInputStream2);    // 읽기용(원본)
BufferedOutputStream bufferedOutputStream
        = new BufferedOutputStream(fileOutputStream2);  // 쓰기용(복사본)

 

다음은 copy함수를 사용하여 소요시간을 측정합니다.

// TODO : 복사(copy)와 함께 소요시간(리턴값) 체크
long bufferTime = copy(bufferedInputStream, bufferedOutputStream);
System.out.println("버터를 사용할때 : " + bufferTime + "ns");

마무리로 파일을 닫아줍니다.

// TODO : 파일 닫기
bufferedInputStream.close();
bufferedOutputStream.close();

 

버퍼를 사용하였을 때 복사소요시간은 다음과 같습니다.

버퍼를 사용할때 : 2299000ns

 

즉, 일반 복사를 할 때보다 버퍼를 사용하여 복사하였을 때 성능향상이 있는 것을 알 수 있습니다.

 

버퍼를 사용하지 않았을 때(일반복사) 118145200ns
버퍼를 사용하였을 때 (버퍼 사용 복사) 2299000ns

 

반응형

'Java > Java 이론' 카테고리의 다른 글

printstream  (0) 2023.10.02
보조스트림 : 기본 자료형으로 입출력하기  (0) 2023.10.02
보조스트림  (0) 2023.09.27
입출력 Stream  (0) 2023.09.27
Arrays 클래스  (0) 2023.09.27

+ Recent posts