[Java] URL로부터 데이터(문자열) 읽어오기

지정된 URL에 존재하는 데이터소스로부터 데이터, 특히 문자열 값으로 읽어오는 자바 코드입니다.

URL url = null;
try {
    url = new URL("http://222.237.78.208:8080/yp_tiles/a/metadata.xml");
} catch(MalformedURLException e1) {
    e1.printStackTrace();
}

InputStream in = null;
try {
    in = url.openStream();
    byte[] buffer = new byte[128];
    int readCount = 0;
    StringBuilder result = new StringBuilder();
   
    while((readCount = in.read(buffer)) != -1) {
        String part = new String(buffer, 0, readCount);
        result.append(part);
    }   
   
    System.out.println(result);
} 
catch (IOException e) {
    e.printStackTrace();
}

위의 코드를 실행하게 되면 해당 URL로부터 가져온 데이터가 문자열로써 result 변수에 저장됩니다. 저장된 결과에 대한 화면 표시는 다음과 같습니다.

사용자 삽입 이미지
위의 결과는 타일맵으로 가공된 데이터에 대한 메타 데이터입니다.

[Java] 파일 복사

fileName이 복사할 대상 파일이고 newFileName이 복사되어 새롭게 생성될 파일명입니다. 근데 좀 살펴볼게… 실제 데이터를 복사(전송) 시키는 12번 코드의 transfer 함수는 실제로 전송된 바이트 수를 반환합니다. 전송하고자 하는 바이트수와 실제로 전송된 바이트 수 사이에 차이가 있을 수 있다는 건데.. 이 부분에 대한 고민을 좀 더 해봐야할 코드입니다.

try {
    File inFile = new File(fileName);
    FileInputStream inputStream = new FileInputStream(inFile);
    
    File outFile = new File(newFileName);
    FileOutputStream outputStream = new FileOutputStream(outFile);
   
    FileChannel fcin = inputStream.getChannel();
    FileChannel fcout = outputStream.getChannel();
   
    long size = fcin.size();    
    fcin.transferTo(0, size, fcout);
   
    fcout.close();
    fcin.close();
    
    outputStream.close();
    inputStream.close();
} catch (Exception e) {
    e.printStackTrace();
}   

[Java] 특정 폴더에서 원하는 확장자를 가지는 파일 목록 구하기

원하는 폴더 안에.. 특정한 확장자를 가지는 파일 목록을 얻어야 할때가 있습니다. 예를 들어서 D:/TEMP라는 폴더안에 확장자가 SHP인 파일의 목록을 배열 형태로 반환하도록 하는 경우이지요. 이때 사용할만한 함수입니다.

private Vector getFileNames(String targetDirName, String fileExt) {
    Vector fileNames = new Vector();
    File dir = new File(targetDirName);
    fileExt = fileExt.toLowerCase();
  
    if(dir.isDirectory()) {
        String dirName = dir.getPath();
        String[] filenames = dir.list(null);
        int cntFiles = filenames.length;
       
        for(int iFile=0; iFile            String filename = filenames[iFile];
            String fullFileName = dirName + "/" + filename;
            File file = new File(fullFileName);
 
            boolean isDirectory = file.isDirectory();
            if(!isDirectory && filename.toLowerCase().endsWith(fileExt)) {
                fileNames.add(fullFileName);
            }
        }
    }

    return fileNames;
 }

제가 이 함수가 필요했던 이유는.. 특정 폴더에 존재하는 수백개의 항공영상이나 수백개의 SHP 파일을 한꺼번에 레이어로 추가하고자 하는 필요 때문이였습니다.

아래의 코드는 안드로이드 기반의 GIS 엔진인 블랙포인트에서 위의 함수를 사용해 25cm 해상도의 192개의 항공영상(GEOTIFF 기준으로 40GB 이상)과 일정한 격자로 나눈  SHP 파일 185개(전체 용량 85MB)를 올리는 코드예입니다.

LayerManager layerMan = map.getLayerManager();
  
String ess = Environment.getExternalStorageState();   
String sdCardPath = null;   
if(ess.equals(Environment.MEDIA_MOUNTED)) {   
    sdCardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    String rootDir = sdCardPath + "/mapdata/yp";
    
    // 항공사진 레이어 추가  
    Vector xrrFiles = getFileNames(rootDir +"/XrR", "xrr");
    for(int i=0; i        ILayer layer = new TileImageLayer("xrr_" + i, xrrFiles.get(i), false);
        layerMan.addLayer(layer);
    }

    // 수치지도 레이어 추가
    Vector cassFiles = getFileNames(rootDir + "/CBND", "shp");
    int cntCbndLyr = cassFiles.size();
    for(int i=0; i        ILayer layer = new ShapeLayer("cbnd_" + i, cassFiles.get(i));
        layerMan.addLayer(layer);
       
        ShapeLayerLabel roadLbl = (ShapeLayerLabel)shpLyr.getLabel();
        roadLbl.setFieldName("JIBUN");
        roadLbl.setEnable(true);
        roadLbl.getFontSymbol().setTextSize(11);
        SimpleDrawShapeTheme roadTheme = (SimpleDrawShapeTheme)shpLyr.getTheme();
        roadTheme.getFillSymbol().setHollow(true);
        roadLbl.getFontSymbol().setTextColor(Color.GREEN);
        roadTheme.getStrokeSymbol().setColor(Color.YELLOW);
}

아래는 위의 코드에 반영된 시스템에 대한 실행 화면입니다. 클릭하면 원본 크기로 볼 수 있습니다.

[Java] URL을 통한 Binary 데이터 받기

자바에서 서버가 제공하는 바이너리 데이터를 받아 저장해 주는 코드입니다. 필요할 때 찾아 보기 쉽도록 정리해 봅니다.

URL url;
try {
    url = new URL("http://somewhere/binary.zip");
  
    URLConnection connection = url.openConnection();
    int contentLength = connection.getContentLength();
    if (contentLength > 0) {
        InputStream raw = connection.getInputStream();
        InputStream in = new BufferedInputStream(raw);
        byte[] data = new byte[contentLength];
        int bytesRead = 0;
        int offset = 0;
        while (offset < contentLength) {
            bytesRead = in.read(data, offset, data.length - offset);
            if (bytesRead == -1) break;
            offset += bytesRead;
        }
        in.close();
  
        if (offset == contentLength) {
            // 바이너리 데이터 준비 완료 !
            return true;
        }
    }
} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

위의 코드는 사용해 보니 문제가 있습니다. 이유는 6번 코드를 통해 서버로부터 받은 데이터의 크기가 항상 옳바르지 않다는 것입니다. 예를 들어 데이터가 클 경우.. -1이 반환되기도 합니다. 이러한 이유로 위의 코드는 사용하면 않되고.. 아래의 코드를 사용하시기 바랍니다.

private boolean requestUrl(String urlString, ByteBuffer out) {
    URL url;
  
    try {
        url = new URL(urlString);
        URLConnection connection = url.openConnection();
        InputStream raw = connection.getInputStream();
        InputStream in = new BufferedInputStream(raw);
        byte[] chunk = new byte[1024];
        int bytesRead = 0;

        while((bytesRead = in.read(chunk)) != -1) {
            out.put (chunk, 0, bytesRead);
        }
   
        out.flip();
        in.close();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }  
    
    return true;
}