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

📄 dbasefilewriter.java

📁 shape file read and write
💻 JAVA
字号:
/*
 *    GeoTools - OpenSource mapping toolkit
 *    http://geotools.org
 *    (C) 2002-2006, Geotools Project Managment Committee (PMC)
 *    (C) 2002, Centre for Computational Geography
 *
 *    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; either
 *    version 2.1 of the License, or (at your option) any later version.
 *
 *    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.
 *
 *    This file is based on an origional contained in the GISToolkit project:
 *    http://gistoolkit.sourceforge.net/
 */
package org.geotools.data.shapefile.dbf;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.geotools.data.shapefile.StreamLogging;
import org.geotools.resources.NIOUtilities;

/**
 * A DbaseFileReader is used to read a dbase III format file. The general use of
 * this class is: <CODE><PRE>
 * DbaseFileHeader header = ...
 * WritableFileChannel out = new FileOutputStream(&quot;thefile.dbf&quot;).getChannel();
 * DbaseFileWriter w = new DbaseFileWriter(header,out);
 * while ( moreRecords ) {
 *   w.write( getMyRecord() );
 * }
 * w.close();
 * </PRE></CODE> You must supply the <CODE>moreRecords</CODE> and
 * <CODE>getMyRecord()</CODE> logic...
 * 
 * @author Ian Schneider
 * @source $URL:
 *         http://svn.geotools.org/geotools/trunk/gt/modules/plugin/shapefile/src/main/java/org/geotools/data/shapefile/dbf/DbaseFileWriter.java $
 */
public class DbaseFileWriter {

    private DbaseFileHeader header;
    private DbaseFileWriter.FieldFormatter formatter = new DbaseFileWriter.FieldFormatter();
    WritableByteChannel channel;
    private ByteBuffer buffer;
    private final Number NULL_NUMBER = new Integer(0);
    private final String NULL_STRING = "";
    private final Date NULL_DATE = new Date();
    private StreamLogging streamLogger = new StreamLogging("Dbase File Writer");

    /**
     * Create a DbaseFileWriter using the specified header and writing to the
     * given channel.
     * 
     * @param header
     *                The DbaseFileHeader to write.
     * @param out
     *                The Channel to write to.
     * @throws IOException
     *                 If errors occur while initializing.
     */
    public DbaseFileWriter(DbaseFileHeader header, WritableByteChannel out)
            throws IOException {
        header.writeHeader(out);
        this.header = header;
        this.channel = out;
        streamLogger.open();
        init();
    }

    private void init() throws IOException {
        buffer = ByteBuffer.allocateDirect(header.getRecordLength());
    }

    private void write() throws IOException {
        buffer.position(0);
        int r = buffer.remaining();
        while ((r -= channel.write(buffer)) > 0) {
            ; // do nothing
        }
    }

    /**
     * Write a single dbase record.
     * 
     * @param record
     *                The entries to write.
     * @throws IOException
     *                 If IO error occurs.
     * @throws DbaseFileException
     *                 If the entry doesn't comply to the header.
     */
    public void write(Object[] record) throws IOException, DbaseFileException {

        if (record.length != header.getNumFields()) {
            throw new DbaseFileException("Wrong number of fields "
                    + record.length + " expected " + header.getNumFields());
        }

        buffer.position(0);

        // put the 'not-deleted' marker
        buffer.put((byte) ' ');

        for (int i = 0; i < header.getNumFields(); i++) {
            String fieldString = fieldString(record[i], i);
            if (header.getFieldLength(i) != fieldString.getBytes().length) {
                // System.out.println(i + " : " + header.getFieldName(i)+" value
                // = "+fieldString+"");
                buffer.put(new byte[header.getFieldLength(i)]);
            } else {
                buffer.put(fieldString.getBytes());
            }

        }

        write();
    }

    private String fieldString(Object obj, final int col) {
        String o;
        final int fieldLen = header.getFieldLength(col);
        switch (header.getFieldType(col)) {
        case 'C':
        case 'c':
            o = formatter.getFieldString(fieldLen, obj == null ? NULL_STRING
                    : obj.toString());
            break;
        case 'L':
        case 'l':
            o = (obj == null ? "F" : obj == Boolean.TRUE ? "T" : "F");
            // o = formatter.getFieldString(
            // fieldLen,
            // o
            // );
            break;
        case 'M':
        case 'G':
            o = formatter.getFieldString(fieldLen, obj == null ? NULL_STRING
                    : obj.toString());
            break;
        case 'N':
        case 'n':
            // int?
            if (header.getFieldDecimalCount(col) == 0) {

                o = formatter.getFieldString(fieldLen, 0,
                        (Number) (obj == null ? NULL_NUMBER : obj));
                break;
            }
        case 'F':
        case 'f':
            o = formatter.getFieldString(fieldLen, header
                    .getFieldDecimalCount(col),
                    (Number) (obj == null ? NULL_NUMBER : obj));
            break;
        case 'D':
        case 'd':
            o = formatter
                    .getFieldString((Date) (obj == null ? NULL_DATE : obj));
            break;
        default:
            throw new RuntimeException("Unknown type "
                    + header.getFieldType(col));
        }

        return o;
    }

    /**
     * Release resources associated with this writer. <B>Highly recommended</B>
     * 
     * @throws IOException
     *                 If errors occur.
     */
    public void close() throws IOException {
        // IANS - GEOT 193, bogus 0x00 written. According to dbf spec, optional
        // eof 0x1a marker is, well, optional. Since the original code wrote a
        // 0x00 (which is wrong anyway) lets just do away with this :)
        // - produced dbf works in OpenOffice and ArcExplorer java, so it must
        // be okay.
        // buffer.position(0);
        // buffer.put((byte) 0).position(0).limit(1);
        // write();
        if (channel.isOpen()) {
            channel.close();
            streamLogger.close();
        }
        if (buffer instanceof MappedByteBuffer) {
            NIOUtilities.clean(buffer);
        }
        buffer = null;
        channel = null;
        formatter = null;
    }

    /** Utility for formatting Dbase fields. */
    public static class FieldFormatter {
        private StringBuffer buffer = new StringBuffer(255);
        private NumberFormat numFormat = NumberFormat
                .getNumberInstance(Locale.US);
        private Calendar calendar = Calendar.getInstance(Locale.US);
        private String emptyString;
        private static final int MAXCHARS = 255;

        public FieldFormatter() {
            // Avoid grouping on number format
            numFormat.setGroupingUsed(false);

            // build a 255 white spaces string
            StringBuffer sb = new StringBuffer(MAXCHARS);
            sb.setLength(MAXCHARS);
            for (int i = 0; i < MAXCHARS; i++) {
                sb.setCharAt(i, ' ');
            }

            emptyString = sb.toString();
        }

        public String getFieldString(int size, String s) {
            buffer.replace(0, size, emptyString);
            buffer.setLength(size);
            // international characters must be accounted for so size != length.
            int maxSize = size;
            if (s != null) {
                buffer.replace(0, size, s);
                int currentBytes = s.substring(0, Math.min(size, s.length()))
                        .getBytes().length;
                if (currentBytes > size) {
                    char[] c = new char[1];
                    for (int index = size - 1; currentBytes > size; index--) {
                        c[0] = buffer.charAt(index);
                        String string = new String(c);
                        buffer.deleteCharAt(index);
                        currentBytes -= string.getBytes().length;
                        maxSize--;
                    }
                } else {
                    if (s.length() < size) {
                        maxSize = size - (currentBytes - s.length());
                        for (int i = s.length(); i < size; i++) {
                            buffer.append(' ');
                        }
                    }
                }
            }

            buffer.setLength(maxSize);

            return buffer.toString();
        }

        public String getFieldString(Date d) {

            if (d != null) {
                buffer.delete(0, buffer.length());

                calendar.setTime(d);
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH) + 1; // returns 0
                                                                // based month?
                int day = calendar.get(Calendar.DAY_OF_MONTH);

                if (year < 1000) {
                    if (year >= 100) {
                        buffer.append("0");
                    } else if (year >= 10) {
                        buffer.append("00");
                    } else {
                        buffer.append("000");
                    }
                }
                buffer.append(year);

                if (month < 10) {
                    buffer.append("0");
                }
                buffer.append(month);

                if (day < 10) {
                    buffer.append("0");
                }
                buffer.append(day);
            } else {
                buffer.setLength(8);
                buffer.replace(0, 8, emptyString);
            }

            buffer.setLength(8);
            return buffer.toString();
        }

        public String getFieldString(int size, int decimalPlaces, Number n) {
            buffer.delete(0, buffer.length());

            if (n != null) {
                numFormat.setMaximumFractionDigits(decimalPlaces);
                numFormat.setMinimumFractionDigits(decimalPlaces);
                numFormat.format(n, buffer, new FieldPosition(
                        NumberFormat.INTEGER_FIELD));
            }

            int diff = size - buffer.length();
            if (diff >= 0) {
                while (diff-- > 0) {
                    buffer.insert(0, ' ');
                }
            } else {
                buffer.setLength(size);
            }
            return buffer.toString();
        }
    }

}

⌨️ 快捷键说明

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