Programmer BS Blog

 by BSPFP

Textile 포매터 문법 요약

글 보관함

Total157254
Today26
Yesterday227

Audacity

PC의 소리를 파일로 저장하는데 사용하는 Recording 프로그램입니다.
국내에는 곰녹음기가 있습니다만...
오래전 어떤 사건 이후로 곰플레이어 등등 그쪽 어플은 즐....
차라리 Source Forge 오픈 소스가 안전하죠. ㅎㅎ

근데 어디에 써먹냐구요?

예를 들면....

아이폰에서 노래를 블루투스로 PC를 통해 나오도록 한 다음 그걸 녹음?
뭐 이런 짓을 구상 중입니다. 하하하하하하....

Audacity로는 안되네요... 쩝... 왜 안되징?

앳파일에서 리얼텍 사운드 드라이버 최신 버전으로 설치했더니... 되네요...
쩝... 한성은 그럼 뭘 올려 놓은 거야???

Trackback Address :: http://bspfp.pe.kr/trackback/353

2012/05/09 00:18

아이폰 탈옥 by BSPFP

BS는 현재 순정 아이폰 5.1을 사용하고 있습니다.
5.1은 아직 Untethered Jailbreak(완탈)이 나오지 않았습니다.
그래서 아이폰을 절대 끄면 안되는 Tethered Jailbreak(반탈)만 가능합니다.

그래서 다운그레이드를 알아보니...
다운그레이드를 하려면 SHSH 를 덤프 받아 둔 것이 필요하더군요.
음... 그런거 없으므로 BS는 탈옥 못합니다. 하하하...
(물론 핸드폰으로 쓰는 동안에는 탈옥할 생각도 없습니다.)

SHSH는 어떻게 만드느냐...

TinyUmbrella

를 받아서 실행한 후에 아이폰을 연결하고 해당 아이폰을 선택해서 Save SHSH를 하면 됩니다.

다운그레이드 방법은 BS가 해보질 않았기 때문에 건너뛰고 대신 관련 툴 링크만 걸어둡니다.

redsn0w
sn0wbreeze
iOS 파일 받는 곳
iTunes 구버전 받는 곳

반탈은 완전 비추천입니다. 그냥 완탈해서 사용하세요.
혹시 모르는 일이니 SHSH는 매번 백업하도록 하세요.
물론 탈옥에 관심 없으신 분은 신경쓰시지 않으셔도 됩니다. 하하하

Trackback Address :: http://bspfp.pe.kr/trackback/352

BS가 전세 구하면서 느끼고 부딪힌 일들을 정리 해 보겠습니다.

1. 중개업자의 말을 믿지 마라
직사각형 집이었습니다. 창문이 양 옆으로 나있습니다. 중개업자 왈 “이쪽 창문은 서남향이고 저쪽 창문은 동남향이라 하루종일 햇볕이 잘 듭니다.” 집은 직사각형인데 말이죠...

2. 집은 해가 떠 있을 때에 보러 다닌다.
그래야 햇볕이 잘 드는지 알 수 있습니다.

3. 나침반 필수
동서남북 대략은 알지만 정확히 알기 힘듭니다. 최근 많이 사용하는 스마트 폰의 앱을 이용하시면 쉽게 확인 됩니다.

4. 벽지 확인
곰팡이 핀 곳은 없는지 반드시 확인합니다. 물론 애기 키우는 집에서는 곰팡이 피할 수는 없습니다. 엄청나게 가습기를 가동하므로 BS의 집도 잠자는 방에는 곰팡이가 있습니다.

5. 수도 확인
잘 사용안 할 것 같은 또는 방금 사용하지 않은 수도꼭지를 틀어서 흰 그릇에 담아봅니다. 녹물이 나오는지 확인 합니다. 녹물이 심한 집은 세면대나 욕조를 봐도 좀 티가 납니다만 확실한 것은 수도물을 받아보시는 겁니다.

6. 보일러 년식 확인
서울의 경우 보일러 설치시 도시가스의 확인을 받도록 되어 있습니다. 이 확인란에 설치일이 기입됩니다. 그것으로부터 보일러의 년식을 알 수 있고 그럼 수명이 다 되어 가는지 2년을 장 쓸 수 있는지 알 수 있습니다.

7. 보일러 모델 확인
보일러 모델을 확인 합니다. 해당 평형에 적합한 것인지 확인합니다. 가끔 돈 아끼려고 용량 작은 보일러를 시공한 집이 있습니다. 경동 보일러의 경우 모델명을 보면 확인이 되더군요. 200시리즈는 40평형, 150시리즈는 30평형으로 나오더군요. 보는 김에 열어도 봅니다. BS가 계약 해지하는 집 보일러는 오래되어 유격이 생겨 열기가 밖으로 세더군요.

8. 난방 온수 분배기 확인
온수 온돌 보일러의 특성상 분배기가 필수인데 분배기를 나온 온수 호스의 길이가 다르면 제대로 난방이 되지 않기에 방 하나도 필요하면 두개의 호스로 설치하곤 합니다. 방 세개, 거실, 부엌 정도라몀 최소 5개 또는 6개의 난방 호스가 설치 되어야 합니다. (약 실평수 22평정도 기준)
만약 분배된 호스가 이보다 적다면 따뜻한 방바닥은 기대할 수 없습니다.

9. 세탁기 위치
세탁기가 놓이는 위치가 거실인 경우가 종종 있더라구요. 거실에 세탁기를 놓고 사는 건 좀...
욕실에 세탁기를 두는 경우 욕실의 크기도 고려해야 합니다. 종종 욕실에 세탁기를 두면 변기에 앉을 때에 무릎이 닿는 집이 있더라구요.
또한 세탁기 위치에 배수가 잘 되는지, 세탁기에 온수 공급이 되는지도 반드시 확인 합니다. 온감에 따라 온수오 세탁을 해야 할 경우가 있으니까요.

10. 겨울철 동파 위험 확인
보일러가 외부에 있는 경우 난방 온수의 열기가 밖으로 새어 나갑니다. 세탁기를 발코니 등에 두는 경우 단열이 제대로 되지 않으면 겨울에 세탁기 사용 불가.

11. 주차장 확인
주차장이 도로면 보다 낮아서 약간의 호우에 잠기는 경우가 있습니다.
주차장 바닥이 기울어 있어서 장시간 주차시 차량에 손상이 가는 경우도 있구요.
주차장에 지붕이 있거나 건물 내부라면 더욱 좋습니다. 비나 눈, 직사광선은 차량의 도색에 치명적입니다.

12. 방법 시설
도둑 맞고 싶지 않다면 반드시 확인해야 할 항목입니다. 방법창 유무와 잠금 장치 이상 여부를 확인해야 합니다.
골목 깊숙이 있는 주택은 현관문을 뜯고 도둑이 들어와 BS의 결혼 예물을 모조리 가져 갔더랬지요.

13. 관리비 확인
아파트가 아닌 주택도 관리비를 받는 경우가 있습니다. 심지어 주차비를 받는 빌라도 있었습니다. 헉!!!

14. 에어컨 실외기 위치
은근히 돈이 들어가는 에어컨 설치. 놓칠 수 없는 항목입니다. 5층 건물에 2층인데 실외기는 무조건 옥상 설치. 이러면 에어컨보다 설치 비용이 비싸지는 경우가...

15. 웃풍
웃풍은 집안에 도는 차가운 기운을 말합니다. 확인이 참 힘듭니다. 물론 살다보면 노하우가 생깁니다만.
벽에 곰팡이 많은 집은 대체로 웃풍이 적습니다.
창문에 유격이 있는지 확인합니다.
창문이 이중창이면 더욱 좋습니다.
현 거주자가 어떤 보완을 해 둔 상태라면 웃풍이 심한 겁니다.
비닐을 입혀 둔 집들도 있고, 문풍지로 도배를 한 집도 있습니다.
반면 겨울철에 반팔 입고 있는 집도 있습니다. (BS가 살던 옥탑방)

16. 등기부 확인
실제 대출 금액과 상관없이 등기부에 채권최고액이 얼마인가 확인해야 합니다. 마치 마이너스 계좌처럼 언제든지 대출을 쓸 수 있거든요. 현재 대출금이 몇백만원이라도 채권최고액이 수억원이라면 대출 수억원 받은 것과 동일합니다. 그리고 최고액과 모든 세입자 보증금 합계가 주택 시세의 70%만 되어도 경매로 넘어가게 되면 보증금 날릴 수 있습니다. 게다가 전세 대출이 안 될 수도 있구요.
그래서 이사는 평일에 하는 것이 좋습니다. 또한 계약하자마자 동사무소 가서 확정일자 받는 것을 추천합니다.

17. 계약서 약관
보통 특약사항 없이 진행됩니다만 필요시 꼭 계약서에 명시해야 합니다. 도배, 장판, 보일러 공사, 욕실 보수, 주차 시설 등등과 같이 계약시에 임대인이 제공하기로 한 내용은 반드시 명시합니다.
그리고 교육, 직장 등 임차인이 어쩔 수 없이 중간에 계약을 해지해야 하는 상황이 발생할 경우 등을 특약으로 정하는 것도 좋습니다.
보통 집주인들은 계약 당시에는 인심이 좋으니 계약서에 많이 기재하도록 하세요.

19. 임대 부동산 소유자 확인
가끔 개념없이 부동산 소유자 딸이나 아들, 배우자가 계약서를 작성하거나 계좌이체를 요구하는 경우가 있는데 이런 거는 절대 피하셔야 합니다. 계약서는 소유자와 직접 작성하고 인감을 찍도록 하고 보증금 전달도 반드시 소유자 본인에게 전달해야 합니다. 월세의 경우 매월 내는 월세금도 마찬가지 입니다.

20. 전입신고
전입신고시 다른 세대가 임대한 부동산에 남아있는지 반드시 확인합니다. 더 좋은 것은 계약 직후 확정일자 받으러 동사무소에 가서 확인 하는 겁니다. 확정일자 받으러 가면 계약서를 가지고 있기 때문에 다른 사람의 주민등록 현황을 알려 줍니다.
가끔 나쁜 주인이 이전 세입자에게 보증금 반환응 하지 않아 저티고 있는 경우가 있어 보증금 일부를 손해 볼 수 있습니다.

여기까지 대충 간단히 주의사항을 적어 보았습니다.

좋은 집 구해서 행복하게 삽시다!!!

Trackback Address :: http://bspfp.pe.kr/trackback/351

내용증명 보내는 방법

살다보니 이런 것도 하게 되는군요.
내용증명은 우체국 가서 합니다.
그럼 내용증명에 대해 간단히 알아보겠습니다.

1. 내용 증명이란?
발송인이 해당 수취인에게 우체국의 창구 또는 정보통신망을 이용하여 어떠한 내용의 문서를 언제 발송하였다는 사실을 우체국이 기록하여 증명하는 특수취급제도입니다.
특정한 형식은 없으나 대부분 법적 증거 자료가 되는 문서를 보낼 것이므로 거짓이나 부풀림없는 내용으로 작성합니다.
등기 우편으로 발송 됩니다.

2. 작성하기

내용증명서

수신인:
주소:
연락처:

발신인:
주소:
연락처:

주제: 간단하게 적습니다
예) 전세보증금 잔금 반환 요청

내용
육하원칙(누가, 언제, 어디서, 무엇을, 어떻게, 왜)에 맞게 작성합니다. 나중에 증거 자료가 될 것이므로 내용을 부풀리거나 거짓을 적으면 안됩니다.

yyyy년 mm월 dd일
발송인 홍길동 (인)

요렇게 작성하시면 무난합니다.
언론 기사처럼 부풀리거나 거짓을 적지 마세요. ㅎㅎㅎ
요금이 장당 계산되므로 간결하게 적고 폰트 적당히 설정하셔서 1장으로 만드세요. 그렇다고 보험 약관처럼 만드시면 곤란합니다. 읽을 수는 있게...
보낼 때 반송 받지 않겠다고 하면, 다른 등기우편과 동일하게 미수취시에 추가 요금이 발생하지 않습니다.

3. 보내기
우선 우체국으로 갑니다. 우체국의 업무는 크게 두가지. 내용증명은 우편 업무이므로 우편 창구로 갑니다.
준비물: 내용증명서 3부, 우편 봉투(우체국에서도 판매 함), 돈
내용증명 문서는 발송인이 하나를 가지고 있고, 우체국에서 하나을 3년간 보관하며, 수취인에게 하나를 전달하므로 동일한 내용의 문서 3부가 필요합니다.
번호표 뽑고 기다립니다.
내용증명 보내러 욌다고 얘기합니다.
보냅니다.

이런 거 저는 안하게 될 거라 생각하고 살았습니다. 그런데 살다보니 이런 거 찾아보게 되고 작성하게 되네요. 적당히 맞춰가며 살고 싶은데 도를 지나치는 사람들이 있습니다.

한바탕 난리를 치고 실손 금액 배상하기로 합의하고 그냥 물러섰습니다. 싸워서 더 받아 낼 수도 있겠으나 BS 성격이 이러합니다. 싸우는 것을 싫어 하거든요.

처음 얘기 꺼냈을 때에는 “세입자가 그냥 사는 거지. 말이 많다.” 라 하더니 싸울 태세로 덤벼드니 원하는대로 합의해주겠으니 용서해 달라네요.

강자에게 약하고 약자에게 강한 참된 집주인들의 모습이네요.

Trackback Address :: http://bspfp.pe.kr/trackback/350

목요일에 이사를 했습니다. 83년에 지어진 아파트입니다.
오래된 아파트 이다보니 보일러실도 크고 창고도 있습니다.
연탄 보일러를 사용했기 때문에 연탄 창고가 필요했겠죠.
지금은 도시가스로 보일러가 되어 있지만요.
문제는 보일러가 방 3개에만 설치가 되어 있고 거실과 부엌에는 없다는거죠. 왠지 사기 당한 기분이네요. 계약 당시에 그런 내용을 듣지 못했거든요.

주인에게 전화했더니
“오래된 아파트가 다 그렇지. 세입자가 뭘 그런 것을 따지냐”
하는 군요. 어이가 없습니다.
그래서
“이건 계약서 내용과 달리 난방에 문제가 있으니 위약금을 받고 계약을 파기해야 겠습니다.”
라고 전달 했더니 태도가 조금 바뀌네요.
일주일 뒤에 부동산에서 만나기로 했습니다.

살다보니 지금 시대에도 보일러가 제대로 없는 집이 있네요.
보일러 공사를 해주지 않으면 계약금과 위약금 받고 집을 옮겨야 할 거 같습니다. 물론 위약금 받기가 쉽지는 않을 겁니다.
대한민국은 “부러진 화살” 영화처럼 돈 많고 권력을 가진 사람이 법 위에 서 있는 나라이니까요.
그래도 최선을 다해서 싸워 볼랍니다.
어떤 일이 일어날지 모르겠으나 최대한 법률도 찾고 판례도 준비해서 딴소리 못하도록 해야 겠네요

Trackback Address :: http://bspfp.pe.kr/trackback/349

1. Calling Convention

[DllImport("SomeDLL.dll", CallingConvention = CallingConvention.Cdecl)

와 같이 명시를 해준다.
기본으로는 __stdcall이다. (Win32 API 사용시 편하도록 한 듯)

2. Character Set

[DllImport("SomeDLL.dll", CharSet = CharSet.Unicode)

와 같이 명시를 해준다.

3. char* 또는 wchar_t* 등으로 받는 방법

int someFunction(wchar_t* outString);

를 가져와서 쓸 때에는

[DllImport("SomeDLL.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
static extern int someFunction(StringBuilder outString);

으로 선언하고

StringBuilder sb = new StringBuilder(bufferLength);
int ret = someFunction(sb);
if (ret == 0)
    someString = sb.ToString();

과 같이 System.Text.StringBuilder를 사용하여 작성한다.

Trackback Address :: http://bspfp.pe.kr/trackback/348

C++의 printf() 계열 또는 boost::format 계열 등에서 사용되는 녀석들과 유사하고도 다른 형식 문자열에 대해 정리 해봤습니다.

using System;

class Program
{
    static void Main(string[] args)
    {
        // 순서만 지정
        Console.WriteLine("{0}, {1}", 1, 2.345678);

        // 우측 정렬 지정
        Console.WriteLine("{0,10}", 1);

        // 좌측 정렬 지정
        Console.WriteLine("{0,-10}", 1);

        // {{ escape 처리
        Console.WriteLine("{{ {0,-10} }}", 1);

        // 타입 지정 1 : 16진수
        Console.WriteLine("{0:X}", 123);

        // 타입 지정 2 : 16진수
        Console.WriteLine(123.ToString("X"));

        Console.ReadKey();

        // Output:
        // 1, 2.345678
        //          1
        // 1
        // { 1          }
        // 7B
        // 7B
    }
}

참고자료

표준 숫자 서식 문자열
사용자 지정 숫자 서식 문자열
표준 날짜 및 시간 서식 문자열
사용자 지정 날짜 및 시간 형식 문자열
표준 TimeSpan 서식 문자열
사용자 지정 TimeSpan 서식 문자열
열거형 형식 문자열
합성 형식 지정
형식 지정 작업 수행
문자열 구문 분석

Trackback Address :: http://bspfp.pe.kr/trackback/347

정말 대충 만들었습니다.
무어라 할 것도 없이 마구마구 막 대충 얼렁뚱땅 만들었습니다.
여차하면 안 쓰일지도 몰라서요. ㅋ

파일은 따로 첨부 안합니다.

using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace ATool
{
    class ExcelWorkSheet
    {
        public int rowCount { get; private set; }
        public int colCount { get; private set; }
        public string this[int row, int col]
        {
            get
            {
                string ret = "";
                if (row >= 1 && row <= rowCount && col >= 1 && col <= colCount && data_[row, col] != null)
                    ret = data_[row, col].ToString();
                if (bTrimData_)
                    ret.Trim();
                return ret;
            }
        }

        public ExcelWorkSheet(Microsoft.Office.Interop.Excel.Worksheet sheet, bool bTrimData)
        {
            var usedRange = sheet.UsedRange;
            this.data_ = usedRange.Value2;
            this.rowCount = usedRange.Rows.Count;
            this.colCount = usedRange.Columns.Count;
            this.bTrimData_ = bTrimData;
        }

        private object[,] data_;
        private bool bTrimData_;
    }

    class ExcelWorkbook : IDisposable
    {
        public ExcelWorkSheet[] worksheets_ { get; private set; }
        public ExcelWorkSheet this[string name]
        {
            get
            {
                ExcelWorkSheet ret;
                if (worksheetByName_.TryGetValue(name, out ret))
                    return ret;
                else
                    return null;
            }
        }
        public ExcelWorkSheet this[int index]
        {
            get
            {
                ExcelWorkSheet ret;
                if (worksheetByIndex_.TryGetValue(index, out ret))
                    return ret;
                else
                    return null;
            }
        }

        public ExcelWorkbook(Microsoft.Office.Interop.Excel.Workbook workbook, bool bTrimData)
        {
            this.workbook_ = workbook;
            this.worksheetByIndex_ = new Dictionary<int, ExcelWorkSheet>();
            this.worksheetByName_ = new Dictionary<string, ExcelWorkSheet>();
            List<ExcelWorkSheet> list = new List<ExcelWorkSheet>();
            foreach (object _sheet in this.workbook_.Sheets)
            {
                Microsoft.Office.Interop.Excel.Worksheet sheet = _sheet as Microsoft.Office.Interop.Excel.Worksheet;
                if (sheet != null)
                {
                    ExcelWorkSheet worksheet = new ExcelWorkSheet(sheet, bTrimData);
                    list.Add(worksheet);
                    worksheetByIndex_.Add(sheet.Index, worksheet);
                    worksheetByName_.Add(sheet.Name, worksheet);
                }
            }
            this.worksheets_ = list.ToArray();
        }

        ~ExcelWorkbook()
        {
            Dispose();
        }

        public void Dispose()
        {
            if (workbook_ != null)
            {
                workbook_.Close();
                Marshal.ReleaseComObject(workbook_);
                workbook_ = null;
            }
        }

        private Microsoft.Office.Interop.Excel.Workbook workbook_;
        private Dictionary<int, ExcelWorkSheet> worksheetByIndex_;
        private Dictionary<string, ExcelWorkSheet> worksheetByName_;
    }

    class ExcelReader : IDisposable
    {
        public ExcelWorkbook openWorkbook(string filename, bool bTrimData = true)
        {
            try
            {
                string filepath = Path.GetFullPath(filename);
                Microsoft.Office.Interop.Excel.Workbook workbook = excelApp_.Workbooks.Open(filepath, ReadOnly: true);
                ExcelWorkbook ret = new ExcelWorkbook(workbook, bTrimData);
                workbooks_.Add(ret);
                return ret;
            }
            catch (Exception ex)
            {
                Utils.errorbox(ex.Message);
                Utils.printError(ex.StackTrace);
                return null;
            }
        }

        public ExcelReader()
        {
            this.excelApp_ = new Microsoft.Office.Interop.Excel.Application();
            this.workbooks_ = new List<ExcelWorkbook>();
        }

        ~ExcelReader()
        {
            Dispose();
        }

        public void Dispose()
        {
            foreach (ExcelWorkbook workbook in workbooks_)
                workbook.Dispose();
            workbooks_.Clear();
            if (excelApp_ != null)
            {
                excelApp_.Quit();
                Marshal.ReleaseComObject(excelApp_);
                excelApp_ = null;
            }

            // EXCEL 프로세스야 사라져라
            GC.GetTotalMemory(false);
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.GetTotalMemory(true);
        }

        private Microsoft.Office.Interop.Excel.Application excelApp_;
        private List<ExcelWorkbook> workbooks_;
    }
}


사용 방법은 다음과 같습니다.

using (ExcelReader reader = new ExcelReader())
using (ExcelWorkbook workbook = reader.openWorkbook(filename, false))
{
	foreach (ExcelWorkSheet sheet in workbook.worksheets_)
	{
		for (int row = 1; row <= sheet.rowCount; ++row)
		{
			for (int col = 1; col <= sheet.colCount; ++col)
			{
				Console.WriteLine("({0}, {1}): {2}", row, col, sheet[row, col]);
			}
		}
	}
}

Trackback Address :: http://bspfp.pe.kr/trackback/346

얼마전까지 1.8 버전 마지막이던 1.8.7 베타 2를 사용했습니다.
그리고 1.9 베타 버전이 좀 나와있어 갈아탔습니다.

문제 하나

  1. 이전에 수정한 Textile 플러그인을 백업하고
  2. 1.9 확장 패키지를 다운 받아 압축을 풀고
  3. 모두 덮어 씌우고
  4. 관리자 페이지로 이동하면
  5. 버전 업에 대한 작업이 자동으로 뜨면 진행하고
  6. 백업한 Textile 플러그인을 다시 적용했습니다.

그런데... 왜? 글 작성에 파일 업로드가 사라졌지?

물론 tinyMCE 를 편집기로 사용하면 볼 수 있습니다.
툴 박스에 버튼이 생기거든요.
하지만 BS는 Textile을 기본 포매터로 사용하기에 편집기를 tinyMCE를 사용할 수 없습니다.
그래서 플러그인에서 tinyMCE를 삭제했는데... 왜! 다시 로그인하면 켜져있지?

결국 플러그인 디렉토리에서 ED_tinyMCE 디렉토리를 삭제해 버렸습니다.

문제 둘

아이폰으로 접속을 했습니다.

  1. 아이폰용 URL이 변경되었습니다.
  2. 새로운 아이폰 인터페이스가 나옵니다.
  3. 그런데 SyntaxHighLighter가 깨집니다.
  4. 그리고 데스크탑 화면 버튼이 동작하지 않습니다.

이런... 베타는 베타입니다.

Trackback Address :: http://bspfp.pe.kr/trackback/345

문제 하나) 너무 느리다!

BS가 회사에서 툴 작성을 하는데 속도가 너무 느려서 왜 그런지 찾아보았습니다.

처음에는 MS의 예제를 참고해서 아래처럼 작성했습니다.

foreach (object _sheet in new Application().Open(filepath, ReadOnly: true).Sheets)
{
	Worksheet = _sheet as Worksheet;
	for (int r = 1; r < 10; ++r)
	{
		for (int c = 1; c < 10; ++c)
		{
			var cell = sheet.Cells[r,c];
			string val = cell.Value2.ToString();
			// ...
		}
	}
}

엄청 느리더군요. 왜?
그래서 다음처럼 Cells로 전체에서 참조하지 않고 UsedRange로 했습니다.

var cell = sheet.UsedRange[r,c];

그래도 느리더군요. 왜?

그래서 아래처럼 수정했습니다.

foreach (object _sheet in new Application().Open(filepath, ReadOnly: true).Sheets)
{
	Worksheet = _sheet as Worksheet;
	var usedRangeValue2 = sheet.UsedRange.Value2;
	for (int r = 1; r < 10; ++r)
	{
		for (int c = 1; c < 10; ++c)
		{
			var cell = usedRangeValue2[r,c];
			string val = cell.Value2.ToString();
			// ...
		}
	}
}

어라??? 빠르다???

C++ 프로그래머의 관점에서 본다면 Worksheet.Cells 또는 Worksheet.UsedRange를 참조하는 것이
루프 밖에 있던 루프 안에 있던 큰 차이가 없어보입니다만...
실제 구현된 내용에서 해당 호출마다 무언가를 다시 하는가봅니다.
가지고 있는 데이터를 인덱서로 반환하는 것이 아니라 매번 새로 만드는 듯한...

엑셀 문서를 읽을 때에는 절대 루프안에서 직접 참조하지 말고 작성해야 합니다.


문제 둘) EXCEL.EXE가 종료 되지 않는다!

엑셀 파일을 툴 초기 로딩에서만 읽고 끝인데...
읽는 루틴이 끝나도 프로세스가 남아있습니다. 이건 뭥미?

그래서 이런 짓을 했더니 드디어 종료되네요.

GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);

신기한 것은 저 루틴들을 디버깅하고 있으면 안 죽는다는 거...

Trackback Address :: http://bspfp.pe.kr/trackback/344

PREV 1 2 3 4 5 ... 33 NEXT