⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filesystemnode.java

📁 shape file read and write
💻 JAVA
字号:
/*
 *    GeoTools - OpenSource mapping toolkit
 *    http://geotools.org
 *    (C) 2004-2006, GeoTools Project Managment Committee (PMC)
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package org.geotools.index.quadtree.fs;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;

import org.geotools.index.quadtree.Node;
import org.geotools.index.quadtree.StoreException;

import com.vividsolutions.jts.geom.Envelope;

/**
 * DOCUMENT ME!
 * 
 * @author Tommaso Nolli
 * @source $URL:
 *         http://svn.geotools.org/geotools/trunk/gt/modules/plugin/shapefile/src/main/java/org/geotools/index/quadtree/fs/FileSystemNode.java $
 */
public class FileSystemNode extends Node {
    private ScrollingBuffer buffer;
    private ByteOrder order;
    private int subNodeStartByte;
    private int subNodesLength;
    private int numSubNodes;

    /**
     * DOCUMENT ME!
     * 
     * @param bounds
     * @param channel
     *                DOCUMENT ME!
     * @param order
     *                DOCUMENT ME!
     * @param startByte
     *                DOCUMENT ME!
     * @param subNodesLength
     *                DOCUMENT ME!
     */
    FileSystemNode(Envelope bounds, int id, Node parent,
            ScrollingBuffer buffer, int startByte, int subNodesLength) {
        super(bounds, id, parent);
        this.buffer = buffer;
        this.subNodeStartByte = startByte;
        this.subNodesLength = subNodesLength;
    }

    public Node copy() throws IOException {
        FileSystemNode copy = new FileSystemNode(getBounds(), id, getParent(),
                buffer, subNodeStartByte, subNodesLength);
        copy.numShapesId = numShapesId;
        copy.shapesId = new int[numShapesId];
        System.arraycopy(shapesId, 0, copy.shapesId, 0, numShapesId);
        copy.numSubNodes = numSubNodes;
        return copy;
    }

    /**
     * DOCUMENT ME!
     * 
     * @return Returns the numSubNodes.
     */
    public int getNumSubNodes() {
        return this.numSubNodes;
    }

    /**
     * DOCUMENT ME!
     * 
     * @param numSubNodes
     *                The numSubNodes to set.
     */
    public void setNumSubNodes(int numSubNodes) {
        this.numSubNodes = numSubNodes;
    }

    /**
     * DOCUMENT ME!
     * 
     * @return Returns the subNodeStartByte.
     */
    public int getSubNodeStartByte() {
        return this.subNodeStartByte;
    }

    /**
     * DOCUMENT ME!
     * 
     * @return Returns the subNodesLength.
     */
    public int getSubNodesLength() {
        return this.subNodesLength;
    }

    /**
     * @see org.geotools.index.quadtree.Node#getSubNode(int)
     */
    public Node getSubNode(int pos) throws StoreException {
        if (this.subNodes.size() > pos) {
            return super.getSubNode(pos);
        }

        try {
            FileSystemNode subNode = null;

            // Getting prec subNode...
            int offset = this.subNodeStartByte;

            if (pos > 0) {
                subNode = (FileSystemNode) getSubNode(pos - 1);
                offset = subNode.getSubNodeStartByte()
                        + subNode.getSubNodesLength();
            }

            buffer.goTo(offset);
            for (int i = 0, ii = subNodes.size(); i < ((pos + 1) - ii); i++) {
                subNode = readNode(pos, this, buffer);
                this.addSubNode(subNode);
            }
        } catch (IOException e) {
            throw new StoreException(e);
        }

        return super.getSubNode(pos);
    }

    /**
     * DOCUMENT ME!
     * 
     * @param channel
     * @param order
     *                DOCUMENT ME!
     * 
     * 
     * @throws IOException
     */
    public static FileSystemNode readNode(int id, Node parent,
            FileChannel channel, ByteOrder order) throws IOException {
        ScrollingBuffer buffer = new ScrollingBuffer(channel, order);
        return readNode(id, parent, buffer);
    }

    static FileSystemNode readNode(int id, Node parent, ScrollingBuffer buf)
            throws IOException {
        // offset
        int offset = buf.getInt();
        double x1;
        double y1;
        double x2;
        double y2;

        // envelope
        x1 = buf.getDouble();
        y1 = buf.getDouble();
        x2 = buf.getDouble();
        y2 = buf.getDouble();
        Envelope env = new Envelope(x1, x2, y1, y2);

        // shapes in this node
        int numShapesId = buf.getInt();
        int[] ids = new int[numShapesId];
        buf.getIntArray(ids);
        int numSubNodes = buf.getInt();

        // let's create the new node
        FileSystemNode node = new FileSystemNode(env, id, parent, buf,
                (int) buf.getPosition(), offset);
        node.setShapesId(ids);
        node.setNumSubNodes(numSubNodes);

        return node;
    }

    /**
     * A utility class to access file contents by using a single scrolling
     * buffer reading file contents with a minimum of 8kb per access
     */
    private static class ScrollingBuffer {
        FileChannel channel;
        ByteOrder order;
        ByteBuffer buffer;
        /** the initial position of the buffer in the channel */
        long bufferStart;

        public ScrollingBuffer(FileChannel channel, ByteOrder order)
                throws IOException {
            this.channel = channel;
            this.order = order;
            this.bufferStart = channel.position();

            // start with an 8kb buffer
            this.buffer = ByteBuffer.allocateDirect(8 * 1024);
            this.buffer.order(order);
            channel.read(buffer);
            buffer.flip();
        }

        public int getInt() throws IOException {
            if (buffer.remaining() < 4)
                refillBuffer(4);
            return buffer.getInt();
        }

        public double getDouble() throws IOException {
            if (buffer.remaining() < 8)
                refillBuffer(8);
            return buffer.getDouble();
        }

        public void getIntArray(int[] array) throws IOException {
            int size = array.length * 4;
            if (buffer.remaining() < size)
                refillBuffer(size);
            // read the array using a view
            IntBuffer intView = buffer.asIntBuffer();
            intView.limit(array.length);
            intView.get(array);
            // don't forget to update the original buffer position, since the
            // view is independent
            buffer.position(buffer.position() + size);
        }

        /**
         * 
         * @param requiredSize
         * @throws IOException
         */
        void refillBuffer(int requiredSize) throws IOException {
            // compute the actual position up to we have read something
            long currentPosition = bufferStart + buffer.position();
            // if the buffer is not big enough enlarge it
            if (buffer.capacity() < requiredSize) {
                int size = buffer.capacity();
                while (size < requiredSize)
                    size *= 2;
                buffer = ByteBuffer.allocateDirect(size);
                buffer.order(order);
            }
            readBuffer(currentPosition);
        }

        private void readBuffer(long currentPosition) throws IOException {
            channel.position(currentPosition);
            buffer.clear();
            channel.read(buffer);
            buffer.flip();
            bufferStart = currentPosition;
        }

        /**
         * Jumps the buffer to the specified position in the file
         * 
         * @param newPosition
         * @throws IOException
         */
        public void goTo(long newPosition) throws IOException {
            // if the new position is already in the buffer, just move the
            // buffer position
            // otherwise we have to reload it
            if (newPosition >= bufferStart
                    && newPosition <= bufferStart + buffer.limit()) {
                buffer.position((int) (newPosition - bufferStart));
            } else {
                readBuffer(newPosition);
            }
        }

        /**
         * Returns the absolute position of the next byte that will be read
         * 
         * @return
         */
        public long getPosition() {
            return bufferStart + buffer.position();
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -