Apache Commons IO 라이브러리

아파치 소프트웨어 재단에서 제공하는 자바 기반의 오픈소스 중  Commons IO 라이브러리가 있습니다. 얼마전 고객과의 미팅을 통해 요구사항을 파악하던 중.. 예상치 못한 기능을 요청받았고 이 기능을 기존 시스템에 추가하려면 상당한 코딩을 해야 할 상황에서 요긴하게 사용한 라이브러리 중에 하나입니다.

사용자 삽입 이미지
이  Commons IO 라이브러리는 기존의 JDK에서 제공하는 클래스들에 대해서 자주 사용하는(Commons 한) 기능들을 클래스화 해 놓은 것으로 이해하면 크게 틀리지 않습니다. 물론 기존의 JDK에서 제공되는 클래스들에 대해 보다 개선된 클래스를 제공하고 있기는 하지만 말입니다.

이 글은 Commons IO 라이브러리의 공식 홈페이지에서 매우 간단한 예제를 통해 해당 라이브러리를 소개하고 있는 글을 한글로 정리한 것입니다. 사실.. 제가 이 Commons IO를 직접 사용한것이 아니고 대용량 파일을 서버로 업로드하는 기능을 제공하는 아파치 소프트웨어 재단에서 제공하는 또 다른 Commons Fileupload 라이브러리에서 이 Commons IO 라이브러리를 사용하는 것을 보고 관심을 가져 보게 되었고 실제 기본적인 내용을 살펴보게 되었습니다.

먼저 해당 URL에 대한 데이터 전체를 문자열로 가져오는 예입니다.

InputStream in = null;
try {
    in = new URL("href='http://www.google.co.kr").openStream();
    System.out.println(IOUtils.toString(in));
} catch (MalformedURLException e) {
     e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    IOUtils.closeQuietly(in);
}

JDK에서 제공하는 기본적인 클래스들을 이용해 위의 코드를 작성했다면 더 긴 코드가 필요했을테고.. 코드가 길다는 것은 그만큼 문제가 발생할 가능성이 높다는 것입니다. 아파치의 Commons IO는 수많은 프로그램에서 사용된 검증된 라이브러리입니다.

다음은 텍스트 파일을 라인별로 읽어 List 컨테이너로 파싱하는 예입니다.

File file = new File("c:/text.txt");
try {
    List lines = FileUtils.readLines(file, "utf-8");
    Iterator it = lines.iterator();
    while(it.hasNext()) {
        System.out.println(it.next());
    }
} catch (IOException e) {
    e.printStackTrace();
}

매우 직관적이고 심플합니다.. 하지만 대용량의 텍스트 파일의 경우 모든 데이터를 읽어 하나의 리스트 컨테이너에 집어 넣으니 메모리 문제가 발생할 수 있다는 점을 염두해 둬야 합니다.

다음은 텍스트 파일을 구성하는 라인을 하나 하나 필요할때마다 읽어 처리할 수 있는 예입니다.

File file = new File("c:/text.txt");
LineIterator it = null;
try {
    it = FileUtils.lineIterator(file);
    while(it.hasNext()) {
        System.out.println(it.next());
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if(it != null) {
        LineIterator.closeQuietly(it);
    }
}

다음은 파일 경로를 정규화해주는 코드입니다.

 String filename = "c:/commons/io/../../lang/../project.txt";
  String normailzed = FilenameUtils.normalize(filename);
  System.out.println(normailzed);

위 코드의 결과는 c:/project.txt가 됩니다.

그리고 해당 경로에 대한 저장 장치의 가용 용량을 얻는 코드입니다.

try {
    long freeSpace = FileSystemUtils.freeSpaceKb("c:/");
    System.out.println(freeSpace + "kb");
} catch (IOException e) {
    e.printStackTrace();
}

이 외에도 파일의 복사, Endian 처리, 다양한 응용 스트림 클래스 등을 제공합니다. 이 처럼 일반적으로 많이 사용되는 IO 루틴에 대해서 더 짧은 코드를 통해서, 그리고 검증된 방법을 통해 구현할 수 있는 라이브러리를 사용한다면 원하는 기능을 더욱 빠르고 안정적으로 추가 개발할 수 있습니다. 이러한 라이브러리를 미리 알고 있는 것으로 개발자의 역량은 기술면에서 더 높아질 것입니다.

안드로이드(Android)에서 sqlite 콘솔 사용

안드로이드에서 기본적으로 사용하는 DB는 sqlite입니다. sqlite는 데이터베이스를 하나의 파일 단위로 하여 여러개의 테이블을 묶어 관리합니다. sqlite는 로컬 DBMS이며 이 파일 하나만 복사해서 다른 곳에 복사하면 아무런 문제 없이 사용할 수 있는 편의성이 있습니다.

여기서 설명하는 sqlite의 버전은 3이며 이 sqlite3에서 사용하는 DBMS 파일을 바이너리 형태로 살펴보면 다음 예와 같습니다.

사용자 삽입 이미지

파일명과 확장자는 의미가 없고 그 파일의 내용을 통해 sqlite의 데이터베이스 파일이라는 것을 인식합니다. 이 데이터베이스 파일에서 정보를 살펴보기 위해서 안드로이드에서 제공하는 SDK를 통해 sqlite3.exe 실행파일을 이용할 수 있습니다.

사용자 삽입 이미지

이 데이터베이스(map.mbtiles 파일)에 정의된 테이블 이름을 보기 위한 명령은 다음과 같습니다.

그리고 테이블에 대한 스키마 정보를 보기 위한 명령은 다음과 같습니다.

이제, 테이블 명과 해당 테이블에 대한 스키마 정보를 파악할 수 있으니 SQL 문을 통해 원하는 정보를 얻을 수 있습니다.

[C#] URL을 통해 이미지(Image) 다운로드(Download)해서 파일(File)로 저장(Save)

웹상의 이미지 URL을 알고 있을때.. 해당 URL로부터 이미지에 대한 데이터를 가져와 파일로 저장하는 C# 함수입니다. 가끔 꼭 필요한 함수인데.. 필요할때 쉽게 찾아 볼 수 있도록 기록해 둡니다.

private bool DownloadRemoteImageFile(string uri, string fileName)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    bool bImage = response.ContentType.StartsWith("image", 
        StringComparison.OrdinalIgnoreCase);
    if ((response.StatusCode == HttpStatusCode.OK ||
        response.StatusCode == HttpStatusCode.Moved ||
        response.StatusCode == HttpStatusCode.Redirect) &&
        bImage)
    {
        using (Stream inputStream = response.GetResponseStream())
        using (Stream outputStream = File.OpenWrite(fileName))
        {
            byte[] buffer = new byte[4096];
            int bytesRead;
            do
            {
                bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                outputStream.Write(buffer, 0, bytesRead);
            } while (bytesRead != 0);
        }

        return true;
    }
    else
    {
        return false;
    }
} 

사용 방법에 대한 예는 다음과 같습니다.

String url = "http://www.there.net/img.png";
String fileName = "d:/a.png";
if (!DownloadRemoteImageFile(url, fileName))
{
    MessageBox.Show("Download Failed: " + url);
}

이 요긴한 함수는 제가 작성한 것은 아니고.. 검색을 통해 찾아 테스트 해보고 실제 프로젝트에 적용해 잘… 쓰고 있는 함수입니다. 출처를 기억하지 못하지만.. 개발해 제공해 준 개발자에게 감사 드립니다.