03.업/08.개발환경2024. 1. 3. 11:48

시스템변수가 수정안될 때 
Powershell > systempropertiesadvanced

 

Posted by 봄날의차
03.업/08.개발환경2023. 12. 6. 15:49

소스트리로 git형상관리사용시에 종종 저장소 데이터가 예전으로 돌아가는 경우가 발생한다.

 

https://kwangho9-develope.blogspot.com/2016/11/git-clienttortoisegit.html

 

Git Client(TortoiseGit) 사용법

프로그램 설치. TortoiseGit를 사용하기 위해서는 Git를 설치해야만 한다. Git for windows 에 접속해서 "Git-2.10.2-64-bit.exe"을 받아서 설치한다. 특별히 설정할 내용이 없기 때문에 "다음"을 선택하면 된...

kwangho9-develope.blogspot.com

 

클라이언트를 바꿨다.

 

Posted by 봄날의차
03.업/01.자바2023. 11. 8. 16:08

StringBuilder urlStr = new StringBuilder(apiUrl+"?");
for (Map.Entry<String, Object> entry : param.entrySet()) {
urlStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}

 

Posted by 봄날의차
03.업/01.자바2023. 11. 1. 14:47

출처 : https://ecolumbus.tistory.com/162

 

Spring Profile 활용 Application.properties

Spring Profile 활용 Application.properties Spring 프로젝트에서 application.properties 파일은 어떤 용도로 사용하는가? 스프링 부트 프로젝트를 이클립스나 인텔리J 에서 세팅하고 나면 src/main/resources/ 아래 appl

ecolumbus.tistory.com

Spring 프로젝트에서 application.properties 파일은 어떤 용도로 사용하는가?

 스프링 부트 프로젝트를 이클립스나 인텔리J 에서 세팅하고 나면 src/main/resources/ 아래 applcation.properties 파일이 생성된다.

 구글에 "스프링 부트 톰캣포트 변경" 이렇게 검색을 해보면  applcation.properties에 server.port = [변경할 포트] 하라는 정보를 흔히 볼 수 있다.

 

 스프링에서 기본적으로 제공하는 여러 옵션들을 지정할 수 있다.

 

 프로파일 그룹이나 파일을 여러개 정의해서 서버 실행 시 입력된 환경변수에 따라 개발자 개인(local), 개발(dev), 운영(prod) 이런 식으로 외부에서 주입받는 값으로 다이나믹하게 사용할 수 있다.


 간단한 예제와 Profile 값을 주입받아서 사용하는 예제를 만들어본다.

키워드를 입력하고 Ctrl + 스페이스 를 누르면 친절히 설명이 나온다.


실습해보자

준비물 : 이클립스, 자바 1.8, 스프링 부트 (Lombok 없어도 됨 습관적으로 추가함 , Spring Web)


첫번째 예제)

우선 Spring Profiile의 간단한 사용법을 알아보자.

application.properties 파일 안에  app.title 변수를 만들고 하드 코딩해서 값을 넣어보고 그 값을 읽어보자.

application.properties

 

 

간단한 컨트롤러를 하나 만들고 @Value("${app.title}") 어노테이션을 사용해서 값을 변수에 대입한다.

package com.example.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Value("${app.title}")
    private String appTitle;
	
	@RequestMapping("/profile")
	public String profile() {
		return appTitle;
	}
}

서버를 실행해서 http://localhost:8080/profile 을 호출해보면 application.properties에 설정한 값 app.title에 할당한 값이 조회가 되는 것을 볼 수 있다.

실행 결과


두 번째 예제)

application-local.properties, application-dev.properties , application-prod.properties 세 개의 파일을 만들고 app.title 변수의 값을 제 각각 주자. Profile에 local, dev, prod 등의 환경변수를 지정해 실행하자.

 

app.title=springboot Profile dev

app.title=springboot Profile local

app.title=springboot Profile prod

 

컨트롤러는 그대로 재활용 한다.

 

파일을 세개로 나눈다. apllocation-{Profile변수}.properties 가 된다.

이클립스 실행 Run  옵션을 준다.

Run - Run Configrations

Run Profile 옵션

어떻게 활용할지 감이 오지 않는가?

profile local이 실행


마무리

서버 실행 시 Profile 변수를 옵션으로 받아 현재 실행되어야 하는 환경을 주입받고, 주입받은 환경 Profile 값에 따라 프로그램 로직을 다이나믹하게 처리할 수 있다.

 

 데이터베이스는 운영, 통합 테스트, 개발 등 환경마다 서버 주소가 일반적으로 다르다. 이럴 때 서버 별로 접속 정보를 구분하고 연결할 수 있다.

 또 예를 들면, 배치 프로그램은 굳이 개발환경에서 스케줄을 돌리지 않아도 될 것이다. 이럴 때 batch.useflag=N 이런 식으로 환경마다 세팅을 해서 사용할 수 있다.

 

Posted by 봄날의차
03.업/15.Vue.js2023. 10. 25. 13:31

chart.js 3.0.0버전으로 설치 후 vue2.6으로 작업

데이터쿼리 조회는 springboot로 작업 

파일1 D:***\bidCalCre.vue
파일2 D:***\bidCalLineChart.vue

>>파일1
1.vue <template></template>

    <!-- 그래프 -->
    <div class="flex flex-col mx-auto" style="width: 1168px;">
      <div class="flex mt-2 mb-5">
        <p>*변동율 추이 line</p>
      </div>
      <table>
          <tr>
            <td> 
              <chart :list_dat_avg="list_dat_avg_line" /> 
              <!-- 
              bidCalLineChart.vue 참조파일에서 호출할 데이터 값 지정
              list_dat_avg 호출할 속성변수명
              -->
            </td>
          </tr>
      </table>
    </div> 
  <!--  그래프 끝 -->
  
2.script
<script lang="ts">  
import Vue from 'vue'
// 1.참조페이지 호출 
import chart from '~/bidCalLineChart.vue' 

..
// 2.컴포넌트 호출 
  components: {
   chart
  },

// 3.data로 지정:전역변수지정 LIST_DAT_AVG 계산시 활용할 변수로 지정해서 사용함...list_dat_avg_line를 이용해서 지정없이 해도 될까..?
    data(){
    ...
        , LIST_DAT_AVG: [] as any
        , list_dat_avg_line: [] as any
    ...
    }  

// 4.페이지로드시에 실행선그래프를 위한 계산을 호출 해서 선그래프를 그린다.
    mounted () {
    ...
        this.getDatAvgList(); // 선그래프를 위한 계산     
    ...
    }
    
// 5.선그래프를 위한 계산  : springboot 호출
    async getDatAvgList(){ // 
      this.LIST_DAT_AVG = [] ; // 초기화 
      const res_list_dat_avg = await this.$axios.post('/***/getDatAvgList', this.BasBidInf );      
      
      this.LIST_DAT_AVG = res_list_dat_avg.data;  
            
      this.initializeLineData() ; // 선그래프호출
    },

// 6.선그래프 작성
     initializeLineData() { //getDatAvgList
     // 데이터를 1부터 12까지 생성하여 rows 배열에 할당    
      this.list_dat_avg_line = []; 
      let len = this.LIST_DAT_AVG.length;

      if(this.LIST_DAT_AVG && Array.isArray(this.LIST_DAT_AVG) && this.LIST_DAT_AVG.length > 0 ){
        
        //데이터맵핑
        for(let i=1;i<=len; i++){
          if(i<=this.LIST_DAT_AVG.length){
            this.list_dat_avg_line.push({
              id: i,
              ym: this.LIST_DAT_AVG[i-1].YM,
              avg_con_amo: this.LIST_DAT_AVG[i-1].AVG_CON_AMO
            })
          } else {
            this.list_dat_avg_line.push({
              id: 1,
              ym: '',
              avg_con_amo: 0
            });
          }
        }
      } else {
        for (let i = 1; i <= len; i++) {
          this.list_dat_avg_line.push({
            id: 1,
            ym: '',
            avg_con_amo: 0
          });
        }
      }

    },
    
>>파일2   
// 1.canvas 설정 id 
<template>
    <div class="line_chart">
      <canvas id="lineChart" width="60" height="60"></canvas>
    </div>
</template>

// 2.chart.js 참조
  <script lang="ts">
  import Vue from "vue";
  import { Chart, registerables } from "chart.js";
  
  Chart.register(...registerables);

// 3.list_dat_avg lineChart 데이터 속성 추가  
// data에lineChart 프로퍼티 전역변수 추가: rowList, lineChart
// watch에list_dat_avg이 변경될 때 실행되는 로직과 새로운 데이터로 차트 업데이트 등의 로직 추가
// mounted에데이터 맵핑과 새로운 데이터로 차트 업데이트로직추가:  this.rowList = this.list_dat_avg; 데이터 맵핑 this.updateChart(); 새로운 데이터로 차트 업데이트
// beforeDestroy : 챠트새로그리기 위해 destroy시킨다.
// renderChart updateChart 구현
  export default Vue.extend({
    //name: 'LineChart',
    props: {
      list_dat_avg: { // lineChart 데이터 속성 추가
        type: Array,
        required: true,
      },
    },
    data() {
      return {
        rowList: [] as any,
        lineChart: null as Chart | null, // lineChart 프로퍼티 전역변수 추가
      };
    },
    watch: {
      list_dat_avg: {
        handler(newRows) {
          // list_dat_avg이 변경될 때 실행되는 로직
          this.rowList = newRows;
  
          // 새로운 데이터로 차트 업데이트 등의 로직을 수행할 수 있습니다.
          this.updateChart();
        },
        deep: true,
        immediate: true, // 컴포넌트가 마운트될 때도 실행
      },
    },
    mounted() {    
      this.rowList = this.list_dat_avg;
      this.updateChart();
    },
    beforeDestroy(){
      if (this.lineChart) {
        this.lineChart.destroy();
      }
    },
    methods: {
      renderChart() {
        const canvas = document.getElementById('lineChart') as HTMLCanvasElement;
        if (!canvas) {
          console.error("Canvas element not found");
          return;
        }
  
        const ctx = canvas.getContext('2d');
        if (!ctx) return;
  
        // 데이터맵핑
        const labels = this.rowList.map((d) => d.ym);
        const data = this.rowList.map((d) => d.avg_con_amo);
  
        this.lineChart = new Chart(ctx, {
          type: 'line',
          data: {
            labels,
            datasets: [{
              label: 'Average Data',
              data,
              fill: false,
              borderColor: 'rgb(75, 192, 192)',
            }],
          },
          options: {
            maintainAspectRatio: false,
            scales: {
              y: {
                beginAtZero: true,
              },
            },
          },
        });
      },
    // 기존 차트 인스턴스를 파괴한 후 Vue의 nextTick 함수를 사용하여 DOM 업데이트 사이클이 완료될 때까지 기다립니다
    async updateChart() {
      if (this.lineChart) {
          this.lineChart.data.labels = this.rowList.map((d) => d.ym);
          this.lineChart.data.datasets[0].data = this.rowList.map((d) => d.avg_con_amo);
          this.lineChart.update();
      } else {
        this.renderChart();
      }
    },
  },
  
  });
  </script>
  
  <style scoped>
    .line_chart {
      width: 1160px;
      height: 400px;
    }
  </style>

 

'03.업 > 15.Vue.js' 카테고리의 다른 글

checkbox 선택 참고  (0) 2023.10.16
Posted by 봄날의차
03.업/11.디비2023. 10. 18. 11:38

참고 : https://pencv.tistory.com/8

 

sql 근사치 조회

sql에서 특정 값(A)을 조회 할 때 해당값이 숫자형식인 경우 A를 찾는데 A가 없고 A에 가까운값들이 있는가를 조회하고 싶을때가 있다. 즉 1을 찿는데 1.11, 0.99와 같은 것들이 이러한 케이스. 이때는

pencv.tistory.com

sql에서 특정 값(A)을 조회 할 때 해당값이 숫자형식인 경우

A를 찾는데 A가 없고 A에 가까운값들이 있는가를 조회하고 싶을때가 있다.

즉 1을 찿는데 1.11, 0.99와 같은 것들이 이러한 케이스.

이때는 ABS함수를 이용하는데 ABS는 절대값을 구하는 함수인데

ABS( A - 1)하면 1에 가까운 값을 찿을 수 있습니다.

 

select *

from tableName

where condition

order by ABS(A-근사값)

limit 1

================ 두개의 컬럼인 경우 

order by ABS(A - 근사값 ), ABS(B - 근사값 ) desc

 

 

'03.업 > 11.디비' 카테고리의 다른 글

MariaDB에 데이터 넣기  (0) 2023.09.22
[펌]쉽게 정리된 SQL  (0) 2023.09.10
SELECT 문장 실행 순서  (0) 2023.07.03
집계함수와NULL  (0) 2023.07.03
tibero6.0 윈도우10 Pro 에 설치하기  (0) 2023.05.16
Posted by 봄날의차
03.업/15.Vue.js2023. 10. 16. 18:06

vue.js N sprintboot로 작업하기 중에 

- 리스트에서 체크박스로 다중 선택해서 삭제하기

1.****\pages\List.vue : 화면
....
<input type="checkbox" :value="eachdata.key" :id="eachdata.key" v-model="checkedRows" @change="getCheckedItem(eachdata.key)">
....
export default Vue.extend({
.... 선언
  data(){    
    return {      
      contentObject: {} as Content
      , checkedRows: [] as string[]
      , nodata: false
    }
  },
....
  methods:{
....
    
    async delBasBid(){
      console.log(this.checkedRows)
      if (sessionStorage.getItem('login')) {        
        try{
          await this.$axios.post('/***/del', { key: this.checkedRows }); // 선언된 변수에 추가 
          location.reload();
        } catch(error) {
          console.error('delBasBid:', error);        
        }        
      }else{
        alert('로그인이 필요합니다.')
        this.$router.push('/auth/login')        
      }
    },
    getCheckedItem(pro_cd){
      console.log(pro_cd)
      console.log(this.checkedRows);
    },
....  
  }


2.***/***Controller.java 
    @PostMapping("/del")
    public ReturnCode delBasBid(@RequestBody Map<String, Object> checkedRows) {        
        Integer code = 0;
        String msg = "";
        List<String> key_list = (List<String>)checkedRows.get("key");
        System.out.println( key_list .toString());
        try {
            for (String key : key_list ) {
                if(key.length() > 0 ) {
                    code = ***Service.delete(key);
                }
            }
            msg = "삭제되었습니다.";
        }
        catch(Exception ex) {
            code = null;
            msg = ex.getMessage();
            ex.printStackTrace();
        }

        return (code);
    }
    
3.***Service.java
    // deleteBasInf
    public Integer deleteBasInf(String pro_cd) {
        return bidCal.deleteBasInf(pro_cd);
    }

    //deleteBidPriPre
    public Integer deleteBidPriPre(String pro_cd) {
        return bidCal.deleteBasInf(pro_cd);
    }

4.mybatis설정.java
    Integer delete(String key);

5.mapper/***.xml
    <select id="delete" parameterType="***" resultType="Integer">
        DELETE FROM tbl WHERE key= #{key};
    </select>

======================================================

자바스크립트보다 수월하게 작업한 듯 해서 정리했다.

'03.업 > 15.Vue.js' 카테고리의 다른 글

lineChart 작업  (0) 2023.10.25
Posted by 봄날의차
03.업/11.디비2023. 9. 22. 17:38

추정가격 BigInt
계약금액 BigInt
낙찰율 DECIMAL

1.숫자, 비율 등의 컬럼도 Varchar타입으로 테이블 만들어 csv 파일의 데이터를 dbever에서 import 시킨다.

  모든 문자컬럼들은 ` ` 으로 감싸서 csv를 밀어넣는다.
2.실제 데이터 타입으로 되어 있는 테이블에 
insert into tbl1 (
    ...

select
   ..., IF(EST_PRI = '#VALUE!',0,EST_PRI)
  ...., IF(CON_AMO = '#VALUE!',0,CON_AMO)

  ...., IF(SUC_BID_RAT = '#VALUE!',0,SUC_BID_RAT)
  ....
from tbl1_str
;
를 실행한다.

마리아디비는 IF 문을 쓰네....

 

'03.업 > 11.디비' 카테고리의 다른 글

[펌]ABS( A - 1)하면 1에 근사치 구하기  (0) 2023.10.18
[펌]쉽게 정리된 SQL  (0) 2023.09.10
SELECT 문장 실행 순서  (0) 2023.07.03
집계함수와NULL  (0) 2023.07.03
tibero6.0 윈도우10 Pro 에 설치하기  (0) 2023.05.16
Posted by 봄날의차
03.업/11.디비2023. 9. 10. 12:10

쉽게 정리된 SQL

[출처]https://okky.kr/articles/1464793 

 

'03.업 > 11.디비' 카테고리의 다른 글

[펌]ABS( A - 1)하면 1에 근사치 구하기  (0) 2023.10.18
MariaDB에 데이터 넣기  (0) 2023.09.22
SELECT 문장 실행 순서  (0) 2023.07.03
집계함수와NULL  (0) 2023.07.03
tibero6.0 윈도우10 Pro 에 설치하기  (0) 2023.05.16
Posted by 봄날의차
03.업/08.개발환경2023. 9. 4. 17:26

***Application 빨간엑스뜨면서 실행이 안될 경우는 build.gradle이 프로젝트에 연결이 안된 경우란다.

 

1.idea 폴더 삭제

2.intelliJ 재실행

3.build.gradle 프로젝트에 연결

- 좌측 메뉴에서 build.gradle더블클릭 : gradle페이지 우클릭 > gradle project 연결..?

: 연결이 되면 gradle project 연결 메뉴가 안보인다.

4.재실행 후 우측에 gradle탭에서 다시로드 아이콘으로 다시 로드 시킨다.

 

 

Posted by 봄날의차
03.업/03.log4j2023. 8. 10. 15:54

D:\###\03.IntelliJWS\프로젝트명\backend\src\main\resources\logback-spring.xml
파일 생성한 후 level 수정해서 사용한다.

기본으로 logback lib가 참조되고 있다.

 

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
    <!-- 로그 파일이 저장될 경로 -->
    <property name="LOG_PATH" value="./logs"/>

    <!-- 로그 파일 이름 -->
    <property name="LOG_FILE_NAME" value="log"/>

    <!-- 로그 출력 패턴 -->
    <property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>

    <!-- 로그 레벨 -->
    <!--
        1) ERROR : 오류 메시지 표시
        2) WARN  : 경고성 메시지 표시
        3) INFO  : 정보성 메시지 표시
        4) DEBUG : 디버깅하기 위한 메시지 표시
        5) TRACE :  Debug보다 훨씬 상세한 메시지 표시

        아래에서는 info로 설정하였는데, 이 경우엔 INFO 보다 위에 있는 DEBUG와 TRACE는 표시하지 않는다.
    -->
    <property name="LOG_LEVEL" value="DEBUG"/>

    <!-- CONSOLE에 로그 출력 세팅 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}[%-5level] : %msg%n</pattern>
        </encoder>
    </appender>
    <!-- File에 로그 출력 세팅 -->
    <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 파일 경로 설정 -->
        <file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>

        <!-- 출력패턴 설정-->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>

        <!-- Rolling 정책 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
            <fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 파일당 최고 용량 kb, mb, gb -->
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거-->
            <maxHistory>30</maxHistory>
            <!--<MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>-->
        </rollingPolicy>
    </appender>

    <!-- log4jdbc 옵션 설정 -->
    <logger name="jdbc" level="OFF" /> <!-- 커넥션 open close 이벤트를 로그로 남긴다. -->
    <logger name="jdbc.connection" level="OFF" /> <!-- SQL문만을 로그로 남기며, PreparedStatement일 경우 관련된 argument 값으로 대체된 SQL문이 보여진다. -->
    <logger name="jdbc.sqlonly" level="DEBUG" /> <!-- SQL문과 해당 SQL을 실행시키는데 수행된 시간 정보(milliseconds)를 포함한다. -->
    <logger name="jdbc.sqltiming" level="DEBUG" /> <!-- ResultSet을 제외한 모든 JDBC 호출 정보를 로그로 남긴다. 많은 양의 로그가 생성되므로 특별히 JDBC 문제를 추적해야 할 필요가 있는 경우를 제외하고는 사용을 권장하지 않는다. -->
    <logger name="jdbc.audit" level="OFF" /> <!-- ResultSet을 포함한 모든 JDBC 호출 정보를 로그로 남기므로 매우 방대한 양의 로그가 생성된다. -->
    <logger name="jdbc.resultset" level="DEBUG" /> <!-- SQL 결과 조회된 데이터의 table을 로그로 남긴다. -->
    <logger name="jdbc.resultsettable" level="OFF" />

    <!-- 로그 전역 세팅 -->
    <root level="${LOG_LEVEL}">
        <!-- 위에 설정한 콘솔 설정 추가 -->
        <appender-ref ref="CONSOLE"/>

        <!-- 위에 설정한 파일 설정 추가 -->
        <appender-ref ref="ROLLING"/>
    </root>

</configuration>

'03.업 > 03.log4j' 카테고리의 다른 글

로그에 찍히는 날짜 에러 체크  (0) 2022.03.15
Posted by 봄날의차
03.업/05.오라클2023. 7. 28. 14:50

1.오라클에서 + 가 붙으면 아웃터조인을 의미하며 + 가 붙은 것의 반대쪽이 기준이 된다.

ANSI표준으로 변경시 이 +가 붙은 것이 leftouter조인 내용에 들어가야 한다.

2.+가 붙지 않은 것이 조인조건에 들어가면 쿼리결과가 달라진다.

'03.업 > 05.오라클' 카테고리의 다른 글

MERGE 문으로 수정 등록하기  (0) 2022.07.07
INSERT INTO SELECT  (0) 2022.06.29
오라클 테이블정보 조회  (0) 2022.06.02
테이블코멘트수정  (0) 2022.05.25
그룹바이 서브쿼리 참조  (0) 2022.01.19
Posted by 봄날의차
03.업/01.자바2023. 7. 14. 13:53

주로 많이 사용하는 utils들 

package egovframework.cts.utl.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipInputStream;

public class CommonUtils {

    public static String leftOfR(String str, String delimeter) {
        int ndx = str.lastIndexOf(delimeter);
        if (ndx == -1) {
            return "";
        }
        else {
            return str.substring(0,ndx);  // ndx위치 제외
        }
    }

    public static String rightOfR(String str, String delimeter) {
        int ndx = str.lastIndexOf(delimeter);
        if (ndx == -1) {
            return "";
        }
        else {
            return str.substring(ndx+delimeter.length(),str.length());
        }
    }

    public static boolean makePath(String filePath) {
        try {
        	Path path = Paths.get(filePath);
            Files.createDirectories(path.getParent()); // 폴더 없으면 생성.
            return true;
        } catch (IOException e) {
        	System.out.println(e.getMessage());
        	e.printStackTrace();
            return false;
        }
    }
    
    public static boolean fileExist(String fileName) {
    	boolean bExist = false;
    	System.out.println("fileExist.fileName:"+fileName);
        bExist = new File(fileName).isFile();
		System.out.println("fileExist:"+bExist);
    	return bExist;
    }

    public static void createFile(File file, ZipInputStream zis) throws Throwable {
    	System.out.println("createFile");
        int MAX_SIZE = 2048000;
    	// 디렉토리 확인
    	File parentDir = new File(file.getParent());
    	System.out.println("parentDir : "+parentDir);
    	// 디렉토리가 없으면 생성하자
    	if(!parentDir.exists()){
    		parentDir.mkdirs();
    	}

    	// 파일 스트림 선언
    	FileOutputStream fos = null;
    	try{
    		fos = new FileOutputStream(file);
    		byte[] buffer = new byte[MAX_SIZE];
    		int size = 0;
    		// Zip스트림으로부터 byte뽑아내기
    		while ((size = zis.read(buffer)) > 0) {
    			// byte로 파일 만들기
    			fos.write(buffer, 0, size);
    		}
    	}catch(Throwable e){
    		System.out.println(e.getMessage());
    	}finally{
    		if(fos != null){
    			try{
    				fos.close();
    			}catch (IOException e) {
    			}
    		}
    	}
    }

}

압축, 압축 풀기도 파일 정리해서 utils로 정리하는 게 좋을 듯

압축풀기를 할때 createFile을 호출한다.

 

Posted by 봄날의차
03.업/08.개발환경2023. 7. 12. 13:13

[펌] https://may9noy.tistory.com/604

dir /b >list.txt

관리자권한의 cmd를 열어서 해당 디렉토리로 이동 후 작성한다.

PowerShell에서 안되네..

 

Posted by 봄날의차
03.업/01.자바2023. 7. 4. 09:40

1.svg 파일 

https://namu.wiki/w/SVG

 

SVG - 나무위키

이 저작물은 CC BY-NC-SA 2.0 KR에 따라 이용할 수 있습니다. (단, 라이선스가 명시된 일부 문서 및 삽화 제외) 기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권

namu.wiki

스케일러블 벡터 그래픽스(Scalable Vector Graphics, SVG)는 2차원 벡터 그래픽을 표현하기 위한 XML 기반의 파일 형식이다.
플래시의 대안으로 HTML5, 모바일 인터넷(웹 앱)분야의 성장, 그리고 레티나 디스플레이가 도입되면서 휴대폰 화면 해상도가 컴퓨터 모니터 해상도를 앞지르면서 SVG가 점점 필요해지기 시작했다.2019년 즈음이면 각종 지도 서비스가 플래시 종료로 마지못해 서비스를 밑바닥부터 다 갈아엎으며 HTML5를 지원해야 해서 SVG에 우호적인 환경이 조성된다.

예) 20230703094537541_C0010301-002-1.024.(공통)좌표전개도(2).svg

<?xml version="1.0" encoding="UTF-8" ?>
<svg xmlns="http://www.w3.org/2000/svg">
    <g transform="translate(-0.000000,0.000000)">
        <g id="line_layer" transform="translate(-2934.390137,7702.255371)">
            <g transform="translate(0.000000,-0.000000)">
            ...

 

2.스크립트에서 svg 접근

<script type="text/javascript" src="<%=request.getContextPath()%>/js/svg/svg-pan-zoom.js"></script> 
<script type="text/javascript">
var panZoom =null;
var text_toggle =1;
var line_toggle =1;
var tTranslageX = 0;
var tTranslageY = 0;
var lTranslageX = 0;
var lTranslageY = 0;

function zoominscreen() {
	panZoom.zoomIn();
}
function zoomoutscreen() {
	panZoom.zoomOut();
}
function resetscreen() { 
	var object = document.getElementById("demo");
	var svgDocument = object.contentDocument;
	var svgb1 = svgDocument.getElementById("text_layer");

	svgb1.setAttributeNS(null,"transform", "translate("+tTranslageX+","+tTranslageY+")");

	var svgb2 = svgDocument.getElementById("line_layer");
	svgb2.setAttributeNS(null,"transform", "translate("+lTranslageX+","+lTranslageY+")");
	text_toggle =1;
	line_toggle =1;

	panZoom.resetZoom();
}
...

3.페이지삽입

<div id='embeddemo' style='width: 792px; height: 592px; border:1px solid black;'>
<script> 
	//FILE_SVG_URL = /data/stp2svg/	
	var filename = "<%=svgName%>";
	var filepath = "<%=svgPathUrl %>" + filename;
    
	//filepath 가 로컬에서 안될 경우 svgPathUrl 에 + filename 해서 경로를 수정해서 반영한다.
	document.write("<object id='demo' type='image/svg+xml' style='width: 790px; height: 900px; border:1px solid black;' data='"+filepath+"' />");	 
</script> 
</div>
<script> 
window.onload = function() { 
	panZoom =svgPanZoom('#demo', {  zoomEnabled: true,  controlIconsEnabled: false ,  fit: true,       center: true});
	initscreen();
    loadDoc();	
};

function initscreen(){
	var object = document.getElementById("demo");
	var svgDocument = object.contentDocument;
	var svgb1 = svgDocument.getElementById("text_layer");
	var transformValue = svgb1.getAttribute("transform");

	var values = transformValue.match(/translate\(([^)]+)\)/)[1].split(',');
	tTranslageX = parseFloat(values[0]);
	tTranslageY = parseFloat(values[1]);

	svgb1 = svgDocument.getElementById("line_layer");
	transformValue = svgb1.getAttribute("transform");
	values = transformValue.match(/translate\(([^)]+)\)/)[1].split(',');
	lTranslageX = parseFloat(values[0]);
	lTranslageY = parseFloat(values[1]);
};

</script>

자바스크립트로 객체에 접근하는 방식으로 접근해서 데이터를 읽어 변수에 할당한다.

 

<g id="line_layer" transform="translate(-2934.390137,7702.255371)">

여기서 숫자만 추출해서 배열에 담기 

...

values = transformValue.match(/translate\(([^)]+)\)/)[1].split(',');

...

 

Posted by 봄날의차
03.업/11.디비2023. 7. 3. 17:19

2. SELECT 문장 실행 순서

 

GROUP BY 절과 ORDER BY가 같이 사용될 때 SELECT 문장은 6개의 절로 구성이 되고, SELECT 
문장의 수행 단계는 아래와 같다.
5. SELECT 칼럼명 [ALIAS명] 1. FROM 테이블명 2. WHERE 조건식 3. GROUP BY 칼럼 
(Column)이나 표현식 4. HAVING 그룹조건식 5.SELECT 6. ORDER BY 칼럼(Column)이나 표현식;


1. 발췌 대상 테이블을 참조한다. (FROM) 

2. 발췌 대상 데이터가 아닌 것은 제거한다. (WHERE)

3. 행들을 소그룹화 한다. (GROUP BY)

4. 그룹핑된 값의 조건에 맞는 것만을 출력한다. (HAVING)

5. 데이터 값을 출력/계산한다. (SELECT)

6. 데이터를 정렬한다. (ORDER BY)

 

옵티마이저가 SQL 문장의 SYNTAX, SEMANTIC 에러를 점검하는 순서이기도 하다.

 

FROM 절에 정의되지 않은 테이블의 칼럼을 WHERE 절, GROUP BY 절, HAVING 절, 
SELECT 절, ORDER BY 절에서 사용하면 에러가 발생한다.

그러나 ORDER BY 절에는 SELECT 목록에 나타나지 않은 문자형 항목이 포함될 수 있다.

단, SELECT DISTINCT를 지정하거나 SQL 문장에 GROUP BY 절이 있거나 또는 SELECT 문에 UNION 연산자가 있으면 열 정의가 SELECT 목록에 표시되어야 한다

관계형 데이터베이스가 데이터를 메모리에 올릴 때 행 단위로 모든 칼럼을 가져오게 되므로, SELECT 절에서 일부 칼럼만 선택하더라도 ORDER BY 절에서 메모리에 올라와 있는 다른 칼럼의 데이터를 사용할 수 있다.

 

'03.업 > 11.디비' 카테고리의 다른 글

MariaDB에 데이터 넣기  (0) 2023.09.22
[펌]쉽게 정리된 SQL  (0) 2023.09.10
집계함수와NULL  (0) 2023.07.03
tibero6.0 윈도우10 Pro 에 설치하기  (0) 2023.05.16
mybatis TIP  (0) 2022.06.23
Posted by 봄날의차
03.업/11.디비2023. 7. 3. 16:49

리포트의 빈칸을 null이 아닌 zero로 표현하기 위해 nvk(iracke)/isnull(sql server)함수를 사용하는 경우가 많은데, 다중 행 함수를 사용하는 경우는 오히려 불필요한 부하가 발생하므로 굳이 nvl함수를 다중 행 함수 안에 사용할 필요가 없다.

 

다중 행 함수는 입력 값으로 전체 건수가 null값인 경우만 함수의 결과가 null이 나오고 전체 건수 중에서 일부만 null인 경우는 null인 행을 다중 행 함수의 대상에서 제외한다.예를 들면 100면중 10명의 성적이 null값일 때 평균을 구하는 다중 행 함수 avg를 사용하면 null값이 아닌 90명의 성적에 대해서 평균값을 구하게 된다.

 

case 표현 사용시 else 절을 생략하게 되면 default 값이 null이다.null은 연산의 대상이 아닌 반면, sum(case month when 1 then sal else 0 end) 처럼 else 절에서 0을 지정하면 불필요하게 0이 sum 연산에 사용되므로 자원의 사용이 많아진다.

가능한 else 절의 상수값을 지정하지 않거나 else절을 작성하지 않도록 한다.

 

오라클의 decode함수는 4번째 인자를 지정하지 않으면 null이 default로 할당된다.

oracle의 sum(nvl(sal,0))

sql server의 sum(isnull(sal,0))

불필요하게 nvl/isnull함수를 사용해 0으로 변환시켜 데이터 건수만큼의 연산이 일어나게 하는 것은 시스템의 자원을 낭비하는 일이다.리포트 출력 때 null이 아닌 0을 표시하고 싶은 경우에는 nvl(sum(sal),0) 이나 isnull(sum(sal),0)처럼 전체 sum의 결과가 null인 경우(대상 건수가 모두 null인 경우)에만 한번 nvl/isnull함수를 사용하면 된다.

 

 

SELECT TEAM_ID
, NVL(SUM(CASE POSITION WHEN 'FW' THEN 1 ELSE 0 END),0) FW
, NVL(SUM(CASE POSITION WHEN 'MF' THEN 1 ELSE 0 END),0) MF
, NVL(SUM(CASE POSITION WHEN 'DF' THEN 1 ELSE 0 END),0) DF
, NVL(SUM(CASE POSITION WHEN 'GK' THEN 1 ELSE 0 END),0) GK
, COUNT(*) SUM 
FROM PLAYER GROUP BY TEAM_ID;

 

CASE 표현의 ELSE 0, ELSE NULL 문구는 
생략 가능하므로 다음과 같이 조금 더 짧게 SQL 문장을 작성할 수 있다. Default 값인 NULL이적용됨. 

SELECT TEAM_ID
, NVL(SUM(CASE POSITION WHEN 'FW' THEN 1 END),0) FW
, NVL(SUM(CASE POSITION WHEN 'MF' THEN 1 END),0) MF
, NVL(SUM(CASE POSITION WHEN 'DF' THEN 1 END),0) DF
, NVL(SUM(CASE POSITION WHEN 'GK' THEN 1 END),0) GK
, COUNT(*) SUM 
FROM PLAYER GROUP BY TEAM_ID;

 

NVL(SUM(CASE POSITION WHEN 'FW' THEN 1 ELSE 0 END),0) FW

 

NVL(SUM(CASE POSITION WHEN 'FW' THEN 1 END),0) FW

 

'03.업 > 11.디비' 카테고리의 다른 글

[펌]쉽게 정리된 SQL  (0) 2023.09.10
SELECT 문장 실행 순서  (0) 2023.07.03
tibero6.0 윈도우10 Pro 에 설치하기  (0) 2023.05.16
mybatis TIP  (0) 2022.06.23
[펌]DISTINCT 와 GROUP BY의 차이  (0) 2021.12.29
Posted by 봄날의차
03.업/01.자바2023. 6. 22. 13:59

>>파일을 다른 서버로 보내서 변환 후 파일을 다시 받는다<<

    // WEB 서버
	public Map<String, Object> requestKos2Svg(String kosFile, String svgFile) throws Exception {
		// TODO Auto-generated method stub

		System.out.println("requestKos2Svg");
		System.out.println(kosFile); // /***/data/edoc/B2014024/C2013935/Y3/하동-***/도면/../C0010101-002-1.악양교.KOS
		System.out.println(svgFile); // /***/data/stp2svg/B2014024/C2013935/Y3/하동-***/도면/../C0010101-002-1.악양교.svg

        String svgFilePath = CommonUtils.leftOfR(svgFile, File.separator);
        String svgFileName = CommonUtils.rightOfR(svgFile, File.separator);

//		CommonUtils.makePath(kosFile);
//		CommonUtils.makePath(svgFile); //폴더생성 확인 하기 파일까지 생성인지 확인 하기

	    String KosConvertUrl = propertiesService.getString("KOS_CONVERT_URL")+"kos2svg.do";
	    //"http://x.x.x.x:8081/kos2svg.do";

	    String fileSvgPath = propertiesService.getString("FILE_SVG_PATH"); // /data/citis5/data/stp2svg/
        System.out.println("fileSvgPath:"+fileSvgPath);
        System.out.println("kosFile:"+kosFile);

        File uploadKosFile = new File(kosFile);
        String boundary = "====" + System.currentTimeMillis()  + "==="; // 각 파트를 구분하는 구분자.

        URL url = new URL(KosConvertUrl);
        System.out.println(url);

        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

        DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());

        String encodedFileName = URLEncoder.encode(uploadKosFile.getName(), "UTF-8");
//        String encodedFileName = uploadKosFile.getName();
        System.out.println("encodedFileName:"+encodedFileName);

        // Upload file
        outputStream.writeBytes("--"+boundary+"\r\n");
        outputStream.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + encodedFileName + "\"\r\n\r\n");

        FileInputStream fileInputStream = new FileInputStream(uploadKosFile);

        int bytesRead;
        byte[] buffer = new byte[4096];
        while ((bytesRead = fileInputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        outputStream.writeBytes("\r\n");
        outputStream.writeBytes("--"+boundary+"--\r\n"); // 전체 요청의 끝.
        fileInputStream.close();
        outputStream.flush();
        outputStream.close();

        //===================== 변환서버결과 대기 중
        //화면으로 리턴할 path와 svgName
        String zipPath = null;
        String zipName = null;
        String resSvgPath = fileSvgPath;
        String resSvgName = null;
        String resSvgLogPath = fileSvgPath;
        String resSvgLogName = null;

        //압축풀기
        FileInputStream zipFileInputStream = null;
        FileOutputStream zipFileOutputStream = null;
        ZipInputStream zis = null;

        int responseStatus = connection.getResponseCode();
        // Download response file
        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            InputStream inputStream = connection.getInputStream();
            String fileName = encodedFileName;
            System.out.println("fileName:"+fileName);
            String disposition = connection.getHeaderField("Content-Disposition");
            System.out.println("disposition:"+disposition);

            if(disposition != null){
            	int idx = disposition.indexOf("filename=");
            	if(idx>0){
            		fileName = disposition.substring(idx+10, disposition.length()-1);
            		fileName = URLDecoder.decode(fileName, "UTF-8");
            		System.out.println("disposition fileName1:"+fileName);

            		// 파일디렉토리경로가 생성되지 않아 stp2svg에 받는다.
            		zipName = fileSvgPath + fileName;
            		System.out.println("disposition zipName:"+zipName);
            	}
            }
        	System.out.println("zipName:"+zipName);

        	Path path = Paths.get(zipName);
    		System.out.println("Path path = Paths.get(zipName)");
    		System.out.println(path);
    		System.out.println("path Parent:"+path.getParent());
    		System.out.println("fileSvgPath:"+fileSvgPath);

    		zipPath = path.getParent().toString();

    		Files.createDirectories(path.getParent());
    		File outputFile = path.toFile();

            // Check if the file exists and delete it if it does
            if (outputFile.exists()) {
                outputFile.delete();
            }

            FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, bytesRead);
            }
            fileOutputStream.close();
            inputStream.close();

            System.out.println("File uploaded and downloaded successfully!");

            // 압축해제
            // 파일 정상적으로 압축이 해제가 되어는가.
            boolean isUnZipChk = false;
        	System.out.println(zipName); // C:\data\citis5\data\stp2svg\20230620164433237_C0000101-001-연결종합평면도.zip
        	String zipUnzipPath = CommonUtils.leftOfR(zipName, File.separator);
        	System.out.println("zipUnzipPath:"+zipUnzipPath);

        	//fileSvgPath + 마지막 폴더
//        	CommonUtils.makePath(zipUnzipPath);

        	File zipFile = new File(zipName);
        	System.out.println("zipFile zipName : " + zipName);

        	FileInputStream fis = null;
        	ZipEntry zipEntry = null;
            
        	try{
	        	// zipFoleName으로 폴더만들기...

//	        	resSvgName = CommonUtils.rightOfR(zipName, ".") + ".svg" ;
//	        	resSvgLogName = CommonUtils.rightOfR(zipName, ".") + ".log" ;

	        	// 파일 스트림
	        	fis = new FileInputStream(zipFile);
	        	// Zip 파일 스트림
	        	zis = new ZipInputStream(fis, Charset.forName("UTF-8"));

	        	// 압축되어 있는 ZIP 파일의 목록 조회
	        	while( (zipEntry = zis.getNextEntry()) != null ){
	        		String fn = zipEntry.getName();
	        		if(CommonUtils.rightOfR(fn, ".").toLowerCase().equals("svg")){
	        			resSvgName = fn;
	        		}else if(CommonUtils.rightOfR(fn, ".").toLowerCase().equals("log")){
	        			resSvgLogName = fn;
	        		}
	        		File file = new File(fileSvgPath, fn);

	        		//entiry가 폴더면 폴더 생성
	        		if(zipEntry.isDirectory()){
	        			file.mkdirs();
	        		}else{
	        			//파일이면 파일 만들기
	        			System.out.println("zipentry가 파일입니다.");
	        			try{
	        				CommonUtils.createFile(file, zis);
	        			}catch(Throwable e){
	        				e.printStackTrace();
	        			}
	        		}
	        	}
	        	isUnZipChk = true;
    		} catch (Exception e) {
    			isUnZipChk = false;
    		} finally {
    			if (zis != null) {
    				try {
    					zis.close();
    				} catch (IOException e) {
    				}
    			}
    			if (fis != null) {
    				try {
    					fis.close();
    				} catch (IOException e) {
    				}
    			}
    		}
        	//unzip end

    		// zip 파일 삭제
        	if(isUnZipChk){
        		Path zipFilePath = Paths.get(zipName);
        		try{
        			Files.deleteIfExists(zipFilePath);
        		} catch (IOException e){
        			System.out.println(e.getMessage());
        			e.printStackTrace();
        		}
        	}

        } else {
            System.out.println("File unzip failed: " + responseStatus);
        }

        System.out.println("File unzip successfully!");

        connection.disconnect();

        //반환 Map 지정하기
        Map<String, Object> responseMap = new HashMap<String, Object>();
        if(responseStatus > -1) {
//        	System.out.println(svgFilePath + File.separator);
        	responseMap.put("responseStatus", responseStatus);
        	responseMap.put("svgPath", resSvgPath);
        	responseMap.put("svgName", resSvgName);
        	responseMap.put("resSvgLogPath", resSvgLogPath);
        	responseMap.put("resSvgLogName", resSvgLogName);
        }

        return responseMap;
	}

 

>> 파일을 web 서버쪽으로 전송 <<

            //4. 파일을 web 서버쪽으로 전송. [svg, log] => zip
            response.setContentType("application/octet-stream");

            String encordedFilename = URLEncoder.encode(zipFileNm,"UTF-8").replace("+", "%20");
            System.out.println("SvgDirectory + zipFileNm : "+SvgDirectory + zipFileNm);

            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encordedFilename + "\"");

            try (InputStream inputStream = new BufferedInputStream(new FileInputStream(SvgDirectory + zipFileNm)); 
                OutputStream outputStream = response.getOutputStream()) {

               byte[] buffer = new byte[4096];
               int bytesRead;

               while ((bytesRead = inputStream.read(buffer)) != -1) {
                   outputStream.write(buffer, 0, bytesRead);
               }
               outputStream.flush();
            } catch (IOException e) {
               e.printStackTrace();
               response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }

attachent 는 여러개 파일을 보내느니 압축해서 압축파일 하나를 보내기로 한다.여러개 파일을 보내는 방법을 못 찾았다.

header에 attachment파일을 zip으로 압축해서 보내고 받기를 추가했다.

 

server.xml에 context 를 추가해서 웹루트밖의 특정폴더에 적재된 data에 접근할 수 있게 수정했다.

<Context docBase="C:\***\data\stp2svg\" path="/data/stp2svg" reloadable="true" />

 

Posted by 봄날의차
03.업/01.자바2023. 6. 22. 13:09

윈도우에서 파일을 웹루트이외의 다른 디렉토리에 업로드 다운로드시에 해당 폴더를

server.xml에서 context로 지정해서 참조시킨다.

<Context docBase="C:\data\***\stp2svg\" path="/data" reloadable="true" />

 

>> 압축하기<<

            //3.[svg, log] 압축하기
            filePaths = new ArrayList<String>();
            filePaths.add(svgFile); //C:\***\data\stp2svg\20230620114531114_C0000101-001-연결종합평면도.svg
            filePaths.add(logFile); //C:\***\data\stp2svg\20230620114531114_C0000101-001-연결종합평면도.log

//            int fidx = 0;
            Path tmpPath = null;
            String zipFileNm = CommonUtils.leftOfR(tempSvgFile, ".") + ".zip";
            File zipFile = new File(SvgDirectory, zipFileNm);
            System.out.println("zipFileNm1:"+zipFileNm); //C:\***\data\stp2svg\20230620114531114_C0000101-001-연결종합평면도.zip

            ZipOutputStream zipOutputStream = null;
            FileInputStream fileInputStream = null;
            byte[] buf = new byte[MAX_SIZE];

            try{

                zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));

                for(String fNm:filePaths){
                	System.out.println("fNm:"+fNm);
                	tmpPath = Paths.get(fNm);
            		System.out.println("Path tmpPath = Paths.get(fNm)");
            		System.out.println(tmpPath);
            		System.out.println("Parent:"+tmpPath.getParent());

            		fileInputStream = new FileInputStream(tmpPath.toFile());
            		zipOutputStream.putNextEntry(new ZipEntry(tmpPath.toFile().getName()));

            		int length = 0;
            		while(((length=fileInputStream.read(buf)) > 0)){
            			zipOutputStream.write(buf, 0, length);
            		}
            		zipOutputStream.closeEntry();
            		fileInputStream.close();
                }
                zipOutputStream.close();
                System.out.println("압축  파일 생성 성공 ");

            } catch(IOException e) {
            	e.printStackTrace();
            	System.out.println(e.getMessage());
            } finally {
            	try{
            	zipOutputStream.closeEntry();
            	zipOutputStream.close();
            	fileInputStream.close();
            	} catch(IOException e){
                	System.out.println(e.getMessage());
            	}
            }

 

>>압축풀기<<

        //압축풀기
        FileInputStream zipFileInputStream = null;
        FileOutputStream zipFileOutputStream = null;
        ZipInputStream zis = null;

        ...
        
            // 압축해제
            // 파일 정상적으로 압축이 해제가 되어는가.
            boolean isUnZipChk = false;
        	System.out.println(zipName); // C:\...\data\stp2svg\20230620164433237_C0000101-001-연결종합평면도.zip
        	String zipUnzipPath = CommonUtils.leftOfR(zipName, File.separator); //압축해제할 폴더경로 
        	System.out.println("zipUnzipPath:"+zipUnzipPath);

        	//fileSvgPath + 마지막 폴더
//        	CommonUtils.makePath(zipUnzipPath);

        	File zipFile = new File(zipName);
        	System.out.println("zipFile zipName : " + zipName);

        	FileInputStream fis = null;
        	ZipEntry zipEntry = null;
// try
        	try{
	        	// zipFoleName으로 폴더만들기...

//	        	resSvgName = CommonUtils.rightOfR(zipName, ".") + ".svg" ;
//	        	resSvgLogName = CommonUtils.rightOfR(zipName, ".") + ".log" ;

	        	// 파일 스트림
	        	fis = new FileInputStream(zipFile);
	        	// Zip 파일 스트림
	        	zis = new ZipInputStream(fis, Charset.forName("UTF-8"));

	        	// 압축되어 있는 ZIP 파일의 목록 조회
	        	while( (zipEntry = zis.getNextEntry()) != null ){
	        		String fn = zipEntry.getName();
	        		System.out.println("fileSvgPath => " + fileSvgPath);
	        		System.out.println("filename(zipentry.getName()) => " + fn);
	        		if(CommonUtils.rightOfR(fn, ".").toLowerCase().equals("svg")){
	        			resSvgName = fn;
	        		}else if(CommonUtils.rightOfR(fn, ".").toLowerCase().equals("log")){
	        			resSvgLogName = fn;
	        		}
	        		File file = new File(fileSvgPath, fn);

	        		//entiry가 폴더면 폴더 생성
	        		if(zipEntry.isDirectory()){
	        			file.mkdirs();
	        		}else{
	        			//파일이면 파일 만들기
	        			System.out.println("zipentry가 파일입니다.");
	        			try{
	        				CommonUtils.createFile(file, zis);
	        			}catch(Throwable e){
	        				e.printStackTrace();
	        			}
	        		}
	        	}
	        	isUnZipChk = true;
                
    		} catch (Exception e) {
    			isUnZipChk = false;
    		} finally {
    			if (zis != null) {
    				try {
    					zis.close();
    				} catch (IOException e) {
    				}
    			}
    			if (fis != null) {
    				try {
    					fis.close();
    				} catch (IOException e) {
    				}
    			}
    		}
        	//unzip end
            
            
            
    		// zip 파일 삭제
        	if(isUnZipChk){
        		Path zipFilePath = Paths.get(zipName);
        		try{
        			Files.deleteIfExists(zipFilePath);
        		} catch (IOException e){
        			System.out.println(e.getMessage());
        			e.printStackTrace();
        		}
        	}

 

>> createFile<<

    public static void createFile(File file, ZipInputStream zis) throws Throwable {
    	System.out.println("createFile");
    	// 디렉토리 확인
    	File parentDir = new File(file.getParent());
    	System.out.println("parentDir : "+parentDir);
    	// 디렉토리가 없으면 생성하자
    	if(!parentDir.exists()){
    		parentDir.mkdirs();
    	}

    	// 파일 스트림 선언
    	FileOutputStream fos = null;
    	try{
    		fos = new FileOutputStream(file);
    		byte[] buffer = new byte[256];
    		int size = 0;
    		// Zip스트림으로부터 byte뽑아내기
    		while ((size = zis.read(buffer)) > 0) {
    			// byte로 파일 만들기
    			fos.write(buffer, 0, size);
    		}
    	}catch(Throwable e){
    		System.out.println(e.getMessage());
    	}finally{
    		if(fos != null){
    			try{
    				fos.close();
    			}catch (IOException e) {
    			}
    		}
    	}
    }

 

 

Posted by 봄날의차
03.업/01.자바2023. 6. 22. 11:11

https://mimah.tistory.com/entry/Java-%ED%8C%8C%EC%9D%BC-%EC%9E%85%EC%B6%9C%EB%A0%A5-4-FileReaderWriter

 

[Java] 파일 입출력 4 - FileReader/Writer

FileReader/Writer 사용 예제 💻 예제 📝 소스 코드 import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java

mimah.tistory.com

로그파일 읽기 메뉴 대상 파일은 *.log 파일이다.

	BufferedReader reader = null;
	try{
		System.out.println("ctsReportPfitPopUp======================================3");
		String fileSvgPath = (String)request.getAttribute("fileSvgPath");
		String logFilePath = fileSvgPath+svgLogName;

		//UTF-8 한글 깨져서 EUC-KR로 수정함.
		reader = new BufferedReader(new InputStreamReader(new FileInputStream(logFilePath), "EUC-KR"));

		String line;
		while (((line = reader.readLine()) != null)){
			out.println(line+"<br>");
		}
	} catch (FileNotFoundException fnfe){
		out.println("파일이 존재하지 않습니다.");
		out.println(fnfe.getMessage());
	}

 

Posted by 봄날의차