package ika.geoimport; import ika.geo.GeoGrid; import ika.gui.ProgressIndicator; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.StringTokenizer; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class EsriASCIIGridReader { public static void main(String[] args) { try { String filePath = "/Users/bernie/Documents/GeoTestData/DEM Data/dhm25 100x100km.asc"; long startTime = System.nanoTime(); GeoGrid grid = EsriASCIIGridReader.read(filePath); ika.geo.GeoImage geoImage = new ika.geo.grid.GridToImageOperator().operate(grid); ika.utils.ImageUtils.displayImageInWindow(geoImage.getBufferedImage()); long endTime = System.nanoTime(); System.out.println((endTime - startTime) / 1000 / 1000); } catch (IOException ex) { ex.printStackTrace(); } } volatile private Exception producerConsumerException = null; private EsriASCIIGridReader() { } /** * Returns whether a reader references valid data that can be read. * @param br * @return * @throws IOException */ public static boolean canRead(BufferedReader br) { try { GridHeaderImporter header = new GridHeaderImporter(); header.readHeader(br, true); return header.isValid(); } catch (Exception exc) { return false; } } /** * Returns whether a file references valid data that can be read. */ public static boolean canRead(String filePath) { BufferedReader br = null; try { File file = new File(filePath); FileInputStream fis = new FileInputStream(file.getAbsolutePath()); InputStreamReader in = new InputStreamReader(fis); br = new BufferedReader(in); return EsriASCIIGridReader.canRead(br); } catch (Exception exc) { return false; } finally { if (br != null) { try { br.close(); } catch (Throwable exc) { } } } } /** Read a Grid from a file in ESRI ASCII format. * @param fileName The path to the file to be read. * @return The read grid. */ public static GeoGrid read(String filePath) throws java.io.IOException { return EsriASCIIGridReader.read(filePath, null); } /** Read a Grid from a file in ESRI ASCII format. * @param fileName The path to the file to be read. * @param progress A WorkerProgress to inform about the progress. * @return The read grid. */ public static GeoGrid read(String filePath, ProgressIndicator progressIndicator) throws java.io.IOException { File file = new File(filePath); InputStream fis = new FileInputStream(file.getAbsolutePath()); EsriASCIIGridReader esriReader = new EsriASCIIGridReader(); GeoGrid grid = esriReader.read(fis, progressIndicator); if (progressIndicator != null && progressIndicator.isAborted()) { return null; } String name = file.getName(); if (!"".equals(name)) { grid.setName(name); } return grid; } /** Read a grid from an InputStream. * @param input The stream to read from. * @param progress A WorkerProgress to inform about the progress. * @return The read grid. */ public static GeoGrid readStream(InputStream input, ProgressIndicator progressIndicator) throws IOException { EsriASCIIGridReader esriReader = new EsriASCIIGridReader(); GeoGrid grid = esriReader.read(input, progressIndicator); if (progressIndicator != null && progressIndicator.isAborted()) { return null; } return grid; } /** Read a grid from a stream in ESRI ASCII format. * @param is The stream to read from. The stream is closed at the end. * @param progress A WorkerProgress to inform about the progress. * @return The read grid. */ public GeoGrid read(InputStream input, ProgressIndicator progressIndicator) throws IOException { // initialize the progress monitor at the beginning if (progressIndicator != null) { progressIndicator.start(); } BufferedReader br = null; try { InputStreamReader in = new InputStreamReader(input); br = new BufferedReader(in); GridHeaderImporter header = new GridHeaderImporter(); String firstGridLine = header.readHeader(br, true); GeoGrid grid = new GeoGrid(header.getCols(), header.getRows(), header.getCellSize()); grid.setWest(header.getWest()); grid.setNorth(header.getSouth() + (header.getRows() - 1) * header.getCellSize()); // http://www.java2s.com/Code/Java/Threads/ProducerconsumerforJ2SE15usingconcurrent.htm BlockingQueue<String> q = new LinkedBlockingQueue<String>(64); q.put(firstGridLine); Producer producer = new Producer(q, br); Thread producerThread = new Thread(producer); producerThread.start(); Consumer consumer = new Consumer(q, grid, header.getNoDataValue(), progressIndicator); Thread consumerThread = new Thread(consumer); consumerThread.start(); try { producerThread.join(); } catch (InterruptedException ex) { consumerThread.interrupt(); } consumerThread.join(); return grid; } catch (InterruptedException ex) { return null; } finally { try { if (br != null) { br.close(); } } catch (Exception exc) { } if (producerConsumerException != null) { throw new IOException(producerConsumerException.getMessage()); } } } /** * Indicates end of file. */ private static final String EOF = "END_OF_FILE"; /** * Reads the grid body line by line. */ private class Producer implements Runnable { private BlockingQueue<String> queue; private BufferedReader reader; Producer(BlockingQueue<String> queue, BufferedReader reader) { this.queue = queue; this.reader = reader; } public void run() { try { // read file line by line and store read lines in blocking queue String line; while ((line = reader.readLine()) != null // check whether this thread has been interrupted && !Thread.currentThread().isInterrupted() // check whether consumer thread has encountered an exception && producerConsumerException == null) { queue.put(line); } // add end-of-file object queue.put(EOF); } catch (Exception ex) { // store the exception for the main thread producerConsumerException = ex; } } } /** * Parses grid lines. */ private class Consumer implements Runnable { private BlockingQueue<String> queue; private float noDataValue; private GeoGrid grid; private ProgressIndicator progressIndicator; private int counter = 0; Consumer(BlockingQueue<String> queue, GeoGrid grid, float noDataValue, ProgressIndicator progressIndicator) { this.queue = queue; this.grid = grid; this.noDataValue = noDataValue; this.progressIndicator = progressIndicator; } public void run() { try { final int nCols = grid.getCols(); final int nRows = grid.getRows(); final int nbrValues = nRows * nCols; do { String str = queue.take(); // test of end of file if (EOF.equals(str)) { // make sure the correct number of values has been read if (counter != nbrValues) { throw new IOException("corrupt Esri Ascii grid file"); } break; } // split each line in tokens and parse the tokens for a float. // One row in the grid might not correspond to a grid row. StringTokenizer tokenizer = new StringTokenizer(str, "\t "); while (tokenizer.hasMoreTokens() // check whether this thread has been interrupted && !Thread.currentThread().isInterrupted() // check whether producer thread has encountered an exception && producerConsumerException == null) { int col = counter % nCols; int row = counter / nCols; ++counter; // make sure we do not read too many cell values if (counter > nbrValues) { throw new IOException("corrupt Esri Ascii grid file"); } float v = Float.parseFloat(tokenizer.nextToken()); grid.setValue(v == noDataValue ? Float.NaN : v, col, row); } // update progress info if (progressIndicator != null) { int row = counter / nCols; int perc = (int) ((double) (row + 1) / nRows * 100); if (!progressIndicator.progress(perc)) { counter = nbrValues; break; } } } while (counter < nbrValues // check whether this thread has been interrupted && !Thread.currentThread().isInterrupted() // check whether producer thread has encountered an exception && producerConsumerException == null); } catch (Exception ex) { // store the exception for the main thread producerConsumerException = ex; } } } }