<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/*
 * WindGenStationDisplay.java
 *
 * Created on July 25, 2006, 11:52 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package usda.weru.util;

import com.klg.jclass.table.TableDataModel;
import com.klg.jclass.table.data.AbstractDataSource;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.nio.channels.FileChannel;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.logging.Level;
import javax.measure.unit.NonSI;
import javax.swing.JOptionPane;
import javax.swing.ProgressMonitor;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
import usda.weru.util.gui.WindGenStationDisplay_n;
import usda.weru.util.table.WepsTableMeta;
import usda.weru.util.windgen.MakeInterpolatedStation;
import usda.weru.weps.location.InterpolatedStation;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.WindgenStation;

/**
 *
 * @author lrdinuki
 */
public final class WindGenStationDisplay extends WindGenStationDisplay_n {

    private static final long serialVersionUID = 1L;

    private static final Logger logger = Logger.getLogger(WindGenStationDisplay.class);

    private static final int WIND_SPEED = 0;
    private static final int WIND_ENERGY = 1;
    private static final int WIND_FRACT = 2;
    private static final int WIND_PREPOND = 3;
    private static final int WIND_DIRECTION = 4;
    WindGenData dataSource;
    private double[][][] cumProb = null;
    private double[][][] intvProb = null;
    private double[][] windTimes = null;

    /**
     *
     */
    protected String[][] cellData = new String[5][12];
    double elevationValue = 1000.0; // default elevation in meters
    double temperature = 20.0; // default temperature Celsius
    double stepSize = 0.1; // width of integrating box
    private double threshold = 8.0;
    private static final int numMonths = 12;
    private static final int numDirections = 16;
    private final double[] boundaries = {1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5,
        9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5,
        18.5, 19.5, 20.5, 25.5, 30.5, 35.5, 40.5, 45.5};
    private final String[] dirNames = {"N-0", "NNE-22", "NE-45", "ENE-67", "E-90", "ESE-112", "SE-135", "SSE-157",
        "S-180", "SSW-202", "SW-225", "WSW-247", "W-270", "WNW-292", "NW-315", "NNW-337"};

    /** Creates a new instance of WindGenStationDisplay
     * @param filename
     * @param station */
    public WindGenStationDisplay(final String filename, final Station station) {
        setTitle("Wind Station Data");
        JCB_station.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String s = (String) JCB_station.getSelectedItem();
                if (s.equals(dataSource.currentStation)) {
                    return;
                }
                getStationData(s);
            }
        });

        JTF_threshold.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String valStr = JTF_threshold.getText();
                double thres = Double.parseDouble(valStr);
                if (thres &lt; 2 || thres &gt; boundaries[boundaries.length - 1]) {
                    javax.swing.JOptionPane.showMessageDialog(null,
                            "Number specified is out of range\n"
                            + "must be between 2 &amp; " + boundaries[boundaries.length - 1],
                            "Number out of range",
                            javax.swing.JOptionPane.ERROR_MESSAGE);
                    NumberFormat cf = NumberFormat.getNumberInstance(Locale.US);
                    cf.setMaximumFractionDigits(0);
                    cf.setMinimumFractionDigits(0);
                    JTF_threshold.setText(cf.format(threshold));
                    return;
                }
                threshold = thres;
                getStationData((String) JCB_station.getSelectedItem());
            }
        });

        Thread task = new Thread("WindGenStation Loader") {

            @Override
            public void run() {
                setEnabled(false);
                loadMeta();
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        setVisible(true);
                    }
                });
                loadData(filename);
                if (station instanceof WindgenStation) {
                    WindgenStation windgenStation = (WindgenStation) station;
                    getStationData(String.valueOf(windgenStation.getWBan()));
                } else if (station instanceof InterpolatedStation) {
                    makeInterpolatedStation((InterpolatedStation) station);
                    addStation(station.getDisplayName());
                }

                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        JCB_station.setSelectedItem(station.getDisplayName());
                        toFront();
                    }
                });
                setEnabled(true);
            }
        };
        task.start();

    }
    Vector&lt;String&gt; intpData = null;

    private void makeInterpolatedStation(InterpolatedStation station) {
        ProgressMonitor progress = new ProgressMonitor(this, "Interpolating", "Please wait...", 0, 10);
        progress.setMillisToDecideToPopup(100);
        progress.setMillisToPopup(200);

        BufferedReader br = null;
        try {
            ConfigData cd = ConfigData.getDefault();
            MakeInterpolatedStation mis = new MakeInterpolatedStation(null);
            mis.setParameter(MakeInterpolatedStation.INTERPOLATE1_EXE, cd.getDataParsed(ConfigData.WindInterp1EXE));
            mis.setParameter(MakeInterpolatedStation.INTERPOLATE2_EXE, cd.getDataParsed(ConfigData.WindInterp2EXE));
            mis.setParameter(MakeInterpolatedStation.WINDGEN_EXE, null);

            mis.setParameter(MakeInterpolatedStation.LAT, String.valueOf(station.getLatLong().latitudeValue(NonSI.DEGREE_ANGLE)));
            mis.setParameter(MakeInterpolatedStation.LON, String.valueOf(station.getLatLong().longitudeValue(NonSI.DEGREE_ANGLE)));
            mis.setParameter(MakeInterpolatedStation.IDX_FILE, cd.getDataParsed(ConfigData.WinIndex));
            mis.setParameter(MakeInterpolatedStation.SIM_START, "0");
            mis.setParameter(MakeInterpolatedStation.SIM_LENGTH, "0");

            String polFile = ConfigData.getDefault().getDataParsed(ConfigData.WindgenInterpolationBoundaryFile);
            TFile pol = polFile != null &amp;&amp; !polFile.isEmpty() ? new TFile(polFile) : null;
            if (pol == null || !pol.exists()) {
                logger.error("Unable to find windgen projection file.");
                return;
            }
            polFile = pol.getAbsolutePath();

            mis.setParameter(MakeInterpolatedStation.POL_FILE, polFile);
            mis.setParameter(MakeInterpolatedStation.WDB, cd.getDataParsed(ConfigData.WinData));

            //don't want mis to automagically cleanup
            mis.setCleanUp(false);
            progress.setProgress(2);
            mis.run();

            if (mis.getOutputFile() != null) {
                //queue it up to be deleted when weps closes
                mis.getOutputFile().getParentFile().deleteOnExit();
            }
            intpData = new Vector&lt;String&gt;();
            br = new BufferedReader(new TFileReader(mis.getOutputFile()));
            br.readLine();
            while (true) {
                String inpLin = br.readLine();
                if (inpLin == null) {
                    break;
                }
                intpData.add(inpLin);
            }
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(WindGenStationDisplay.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception ex) {
                    java.util.logging.Logger.getLogger(WindGenStationDisplay.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            progress.close();

        }
    }

    private void loadData(String filename) {
        dataSource = new WindGenData(this);
        if (dataSource.load(this, new TFile(filename))) {
            WT_windGenTable.setDataSource(dataSource);
        }

    }

    /**
     *
     * @param filename
     */
    public WindGenStationDisplay(String filename) {
        this(filename, null);
    }

    private void loadMeta() {
        TFile file = new TFile("tables/windgendisp.xml");
        WepsTableMeta meta = new WepsTableMeta();
        meta.fromFile(file);
        WT_windGenTable.setMeta(meta);
    }

    private void parseElevation(Vector&lt;String&gt; selVec) {
        String inpLin = selVec.get(0); //elevation in first line
        StringTokenizer st = new StringTokenizer(inpLin);
        for (int edx = 0; st.hasMoreTokens() &amp;&amp; edx &lt; 6; edx++) {
            st.nextToken();
        }
        String elevStr = st.nextToken();
        JL_elevation.setText(elevStr);
        elevationValue = Double.parseDouble(elevStr);
    }

    private void parseWindTimes(Vector&lt;String&gt; selVec) {
        windTimes = new double[numDirections][];
        for (int ddx = 0; ddx &lt; numDirections; ddx++) {
            String[] inpArr = new String[numMonths];
            windTimes[ddx] = new double[numMonths];
            String inpLin = selVec.get(ddx + 1); //skip the first line, use next 16
            StringTokenizer st = new StringTokenizer(inpLin);
            for (int mdx = 0; st.hasMoreTokens(); mdx++) {
                inpArr[mdx] = st.nextToken();
                if (ddx == 0) {
                    cellData[ddx][mdx] = inpArr[mdx];
                }
                windTimes[ddx][mdx] = Double.parseDouble(inpArr[mdx]);
            }
        }
    }

    /**
     *
     * @param inpStr
     * @return
     */
    public static String parseWinCmd(String inpStr) {
        StringTokenizer st = new StringTokenizer(inpStr);
        String fileToken = null;
        while (st.hasMoreTokens()) {
            fileToken = st.nextToken();
            if (fileToken.startsWith("-f") || fileToken.startsWith("-F")) {
                break;
            }
            fileToken = "";
        }
        if (fileToken.length() == 0) {
            return "./db/wind_gen/wind_test.wdb";
        }
//		if (fileToken.length() == 0) return "C:/weps/weps1.install/db/wind_gen/wind_gen_his.wdb";

        if (fileToken.length() &gt; 2) {
            return fileToken.substring(2);
        }

        if (st.hasMoreTokens()) {
            return st.nextToken();
        }

        return "./db/wind_gen/wind_gen_his.wdb";

    }

    private void parseWindSpeeds(Vector&lt;String&gt; selVec) {
        cumProb = new double[numMonths][][];
        intvProb = new double[numMonths][][];
        for (int mdx = 0; mdx &lt; numMonths; mdx++) {
            cumProb[mdx] = new double[numDirections][];
            intvProb[mdx] = new double[numDirections][];
            for (int ddx = 0; ddx &lt; numDirections; ddx++) {

                // load cumulative probability curve for each direction
                String inpLin = selVec.get(mdx * numDirections + ddx + 18); //skip the direction data, use next 16*12
                StringTokenizer st = new StringTokenizer(inpLin);
                int numTok = st.countTokens();
                String[] inpArr = new String[numTok];
                cumProb[mdx][ddx] = new double[numTok + 2];
                intvProb[mdx][ddx] = new double[numTok + 2];
                for (int pdx = 0; st.hasMoreTokens(); pdx++) {
                    inpArr[pdx] = st.nextToken();
                    if (mdx == 0 &amp;&amp; ddx == 0 &amp;&amp; pdx &lt; cellData[1].length) {
                        cellData[1][pdx] = inpArr[pdx];
                    }
                    cumProb[mdx][ddx][pdx] = Double.parseDouble(inpArr[pdx]);
                }
                cumProb[mdx][ddx][numTok] = 1.0; // put 1 in last 2 positions
                cumProb[mdx][ddx][numTok + 1] = 1.0;

                // convert cumulative curve to interval values
                intvProb[mdx][ddx] = new double[numTok + 2];
                for (int pdx = 1; pdx &lt; cumProb[mdx][ddx].length; pdx++) {
                    try {
                        double deltaY = cumProb[mdx][ddx][pdx] - cumProb[mdx][ddx][pdx - 1];
                        double deltaX = boundaries[pdx] - boundaries[pdx - 1];
                        intvProb[mdx][ddx][pdx] = deltaY / deltaX;
                    } catch (ArrayIndexOutOfBoundsException f) {
                        // wind prob array &gt; # of boundaries -- skip it
                        //System.err.println("WGD_pWD: " + f);
                    }
                }
            }
        }
    }

    private void getStationData(String station) {
        Vector&lt;String&gt; v = (station != null &amp;&amp; station.toLowerCase().startsWith("interpolated"))
                ? intpData : dataSource.parseFile(station);
        parseElevation(v);
        parseWindTimes(v);
        parseWindSpeeds(v);
        calcThreshold();
        calcEWP();
        calcPrevailingWind();
        dataSource.fireDataReset();
        WT_windGenTable.repaint();
    }

    private void calcThreshold() {
        int tdx = 0;

        while (boundaries[tdx] &lt; threshold &amp;&amp; tdx &lt; boundaries.length) {
            tdx++;
        }

        for (int mdx = 0; mdx &lt; numMonths; mdx++) {
            double overThreshold = 0.0;
            for (int ddx = 0; ddx &lt; numDirections; ddx++) {
                try {
                    // find interpolation fraction between two boundary
                    // points
                    double interp = (threshold - boundaries[tdx - 1])
                            / (boundaries[tdx] - boundaries[tdx - 1]);
                    // calculate the interpolated value for winds over
                    // theshold and multiply by the fraction of time
                    // the wind is coming from that direction and
                    // normalize by dividing by number of wind
                    // directions (16);
                    double windSpeedProb = 1 - (cumProb[mdx][ddx][tdx - 1]
                            + interp * (cumProb[mdx][ddx][tdx] - cumProb[mdx][ddx][tdx - 1]));
                    double addOn = windSpeedProb * windTimes[ddx][mdx] / 100;
                    overThreshold += addOn;

                } catch (ArrayIndexOutOfBoundsException e) {
                    // if array doesn't have any winds over threshold,
                    // just skip that direction
                }
            }

            NumberFormat cf = NumberFormat.getNumberInstance(Locale.US);
            cf.setMaximumFractionDigits(1);
            cf.setMinimumFractionDigits(1);

            cellData[WIND_SPEED][mdx] = cf.format(overThreshold * 100);
        }
    }

    private void calcEWP() {
        int tdx = 0;
        // magic formula for air density based upon elev and temp
        double airDensity = 348.56 * ((1.013 - 0.1183 * (elevationValue / 1000)
                + 0.0048 * (elevationValue / 1000) * (elevationValue / 1000))
                / (temperature + 273.1));
        double weFactor = 3.6 * 24 * 0.5;
        NumberFormat cf = NumberFormat.getNumberInstance(Locale.US);
        cf.setMaximumFractionDigits(0);
        cf.setMinimumFractionDigits(0);

        while (boundaries[tdx] &lt; threshold &amp;&amp; tdx &lt; boundaries.length) {
            tdx++;
        }

        double[] monWindEnrgArr = new double[numMonths];
        double totalWindEnrg = 0;

        // calc total &amp; monthly energies by month
        for (int mdx = 0; mdx &lt; numMonths; mdx++) {
            double monWindEnrg = 0.0;
            // calc wind enrg by direction
            for (int ddx = 0; ddx &lt; numDirections; ddx++) {

// calculate wind enrg from short first interval
                double dirWindEnrg = 0.0;
                int ntdx = tdx;
                if (ntdx &gt;= intvProb[mdx][ddx].length) {
                    continue;
                }

                double curPos = threshold;

                if ((threshold % stepSize) &gt; 0.000000001) {
                    double currentStepSize = stepSize - (threshold % stepSize);
                    curPos += currentStepSize / 2;
                    double stepValue = intvProb[mdx][ddx][ntdx] * (curPos - threshold) * curPos * curPos * currentStepSize;
                    dirWindEnrg += stepValue;
                    curPos += currentStepSize / 2;
                }

                curPos += stepSize / 2;

                try {

                    int stpIdx = 0;
                    while (ntdx &lt; intvProb[mdx][ddx].length) {
                        while (curPos &lt;= boundaries[ntdx]) {
                            double stepValue = intvProb[mdx][ddx][ntdx] * (curPos - threshold) * curPos * curPos * stepSize;
                            dirWindEnrg += stepValue;
                            curPos += stepSize;
                            stpIdx++;
                        }
                        ntdx++;
                    }
                } catch (ArrayIndexOutOfBoundsException e) {
                    //System.err.println("WGD_cWEP: AIOOBE");
                }
                monWindEnrg += weFactor * airDensity * dirWindEnrg * windTimes[ddx][mdx] / 100;
            }
            cellData[WIND_ENERGY][mdx] = cf.format(monWindEnrg);
            monWindEnrgArr[mdx] = monWindEnrg;
            totalWindEnrg += monWindEnrg;
        }

        cf.setMaximumFractionDigits(1);
        cf.setMinimumFractionDigits(1);
        for (int mdx = 0; mdx &lt; numMonths; mdx++) {
            cellData[WIND_FRACT][mdx] = cf.format(monWindEnrgArr[mdx] * 100 / totalWindEnrg);
        }
        cf.setMaximumFractionDigits(0);
        cf.setMinimumFractionDigits(0);
        JL_avgEnergy.setText(cf.format(totalWindEnrg / 12));
    }

    private void calcPrevailingWind() {
        int tdx = 0;

        NumberFormat cf = NumberFormat.getNumberInstance(Locale.US);
        cf.setMaximumFractionDigits(1);
        cf.setMinimumFractionDigits(1);

        // find threshold boundary
        while (boundaries[tdx] &lt; threshold &amp;&amp; tdx &lt; boundaries.length) {
            tdx++;
        }

        double[][] windErosionForces = new double[numMonths][numDirections];
        double[][] paraForces = new double[numMonths][numDirections];
        double[][] perpForces = new double[numMonths][numDirections];
        double[][] posvForces = new double[numMonths][numDirections];
        double[][] ratioForces = new double[numMonths][numDirections];

        for (int mdx = 0; mdx &lt; numMonths; mdx++) {

            // calc wind forces by month and direction
            for (int ddx = 0; ddx &lt; numDirections; ddx++) {
                try {
                    double firstFrac = (boundaries[tdx] - threshold) / (boundaries[tdx] - boundaries[tdx - 1]);
                    windErosionForces[mdx][ddx] = firstFrac * Math.pow(((boundaries[tdx] + threshold) / 2), 3) * intvProb[mdx][ddx][tdx] * windTimes[ddx][mdx];
                    for (int pdx = tdx + 1; pdx &lt; intvProb[mdx][ddx].length; pdx++) {
                        windErosionForces[mdx][ddx] += Math.pow(((boundaries[pdx] + boundaries[pdx - 1]) / 2), 3) * intvProb[mdx][ddx][pdx] * windTimes[ddx][mdx];
                    }
                } catch (ArrayIndexOutOfBoundsException e) {
                }

            }

            for (int ddx = 0; ddx &lt; numDirections; ddx++) {
                for (int adx = 0; adx &lt; numDirections; adx++) {
                    double cos = Math.cos((adx - ddx) * 22.5 * Math.PI / 180);
                    double sin = Math.sin((adx - ddx) * 22.5 * Math.PI / 180);
                    paraForces[mdx][ddx] += windErosionForces[mdx][adx] * Math.abs(cos);
                    perpForces[mdx][ddx] += windErosionForces[mdx][adx] * Math.abs(sin);
                    if (cos &gt; 0) {
                        posvForces[mdx][ddx] += windErosionForces[mdx][adx] * cos;
                    }
                }
                try {
                    ratioForces[mdx][ddx] = paraForces[mdx][ddx] / perpForces[mdx][ddx];
                } catch (Exception f) {
                    ratioForces[mdx][ddx] = Double.NaN;
                }
            }

            double maxRatio = 0.0;
            int maxDirection = 0;
            for (int ddx = 0; ddx &lt; numDirections; ddx++) {
                if (maxRatio &lt; ratioForces[mdx][ddx]) {
                    maxRatio = ratioForces[mdx][ddx];
                    maxDirection = ddx;
                }
            }
            if (posvForces[mdx][maxDirection] * 2 &lt; paraForces[mdx][maxDirection]) {
                maxDirection = (maxDirection + numDirections / 2) % numDirections;
            }

            cellData[WIND_PREPOND][mdx] = cf.format(maxRatio);
            cellData[WIND_DIRECTION][mdx] = dirNames[maxDirection];
        }
    }

    /**
     *
     * @param s
     */
    public void addStation(String s) {
        JCB_station.addItem(s);
    }
}

class WindGenData extends AbstractDataSource implements TableDataModel {

    private static final long serialVersionUID = 1L;

    private static final Logger logger = Logger.getLogger(WindGenData.class);
    private List&lt;String&gt; c_keyMap;
    private List&lt;Object[]&gt; c_data;
    private TFile file;
    private final HashMap&lt;String, Number&gt; map = new HashMap&lt;String, Number&gt;();
    private final HashMap&lt;String, String&gt; idmap = new HashMap&lt;String, String&gt;();
    private final WindGenStationDisplay parent;
    protected String currentStation;
    String[][] cellData = new String[5][12];
    private final String[] monthNames = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

    public WindGenData(WindGenStationDisplay parent) {
        this.parent = parent;
        fireDataReset();
    }

    @Override
    public int getNumColumns() {
        return 12;
    }

    @Override
    public int getNumRows() {
        return 5;
    }

    @Override
    public Object getTableColumnLabel(int columnIndex) {
        return monthNames[columnIndex];
    }

    @Override
    public Object getTableDataItem(int rowIndex, int columnIndex) {
        try {
            String s = parent.cellData[rowIndex][columnIndex];
            return s;
        } catch (Exception e) {
            return "ERR";
        }
    }

    @Override
    public Object getTableRowLabel(int rowIndex) {
        int a = 21349;
        switch (rowIndex) {
            case 0:
                return "Winds &gt; Threshold";
            case 1:
                return "Energy kJ/m^2/day";
            case 2:
                return "Monthly Percent";
            case 3:
                return "Preponderance";
            case 4:
                return "PWED";
            default:
                return "x";
        }
    }

    public Vector&lt;String&gt; parseFile(String station) {
        long index = 0;
        String tmp = station;
        if (map.get(tmp) == null) {
            tmp = idmap.get(station);
        }

        Number number = map.get(tmp);

        if (number != null) {
            index = number.longValue();
        } else {
            logger.warn("Unable to find index for " + (station != null ? station : "[NULL Station]"));
        }
        Vector&lt;String&gt; data = new Vector&lt;&gt;();
        String inLine;
        BufferedReader in = null;
        try {
            java.io.FileInputStream fin = new java.io.FileInputStream(file);
//            fin.getChannel().position(index);
            in = new BufferedReader(new InputStreamReader(fin));
            inLine = in.readLine();

            for (int i = 0; i &lt; index; i++) {
                in.readLine();
            }

            while ((inLine = in.readLine()) != null) {
                if (inLine.startsWith("#")) {
                    break;
                } else {
                    data.add(inLine);
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception e) {
                logger.error("Error closing file stream.", e);
            }

        }
        currentStation = tmp;
        if (parent.JCB_station.getSelectedItem().equals(currentStation) == false) {
            final String tmp2 = tmp;

            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    parent.JCB_station.setSelectedItem(tmp2);
                }
            });
        }

        return data;
    }

    public boolean load(Component parent, TFile file) {
        this.file = file;
        String inLine;
        long position = 0;
        boolean success = true;
        String station;
        //read the file one line at a time into a vector for processing
        ProgressMonitor progress = null;
        try {
            java.io.FileInputStream fileStream = new java.io.FileInputStream(file);
            FileChannel channel = fileStream.getChannel();
            progress = new ProgressMonitor(parent, "Loading Table Data...", file.getName(), 0, (int) channel.size());
            progress.setMillisToDecideToPopup(350);
            progress.setMillisToPopup(500);
            InputStreamReader streamReader = new InputStreamReader(fileStream);
            LineNumberReader in = new LineNumberReader(streamReader);
            StringTokenizer s;
            //add parsing here...
            while ((inLine = in.readLine()) != null) {
                progress.setProgress((int) channel.position());
                if (inLine.startsWith("#")) {
                    s = new StringTokenizer(inLine, " ");
                    s.nextToken();
                    String stationID = s.nextToken();
                    StringBuilder sb = new StringBuilder();
                    while (s.hasMoreTokens()) {
                        sb.append(" " + s.nextToken());
                    }
                    station = sb.toString().trim();
                    idmap.put(stationID, station);
                    map.put(station, position);
                }
                position = in.getLineNumber();
//                position += inLine.length() + 1;
            }
            in.close();
            streamReader.close();
            fileStream.close();

            Set&lt;String&gt; keyset = map.keySet();
            Vector&lt;String&gt; l = new Vector&lt;&gt;();
            l.addAll(keyset);
            Collections.sort(l);
            for (String str : l) {
                this.parent.addStation(str);
            }

        } catch (OutOfMemoryError oome) {
            progress.close();
            JOptionPane.showMessageDialog(parent, "The data file is too large.", "Out of Memory", JOptionPane.ERROR_MESSAGE);
            success = false;
        } catch (Exception e) {
            e.printStackTrace();
            success = false;
        }
        fireDataReset();
        return success;

    }
}
</pre></body></html>