设为首页 加入收藏

TOP

TinyDBF-200行写个DBF解析器(二)
2014-11-24 00:38:23 来源: 作者: 【 】 浏览:25
Tags:TinyDBF-200 DBF 解析
dCount() + "。"); } } protected abstract Field readField() throws IOException; protected abstract void readHeader() throws IOException; private void skipHeaderTerminator() throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocate(1); readByteBuffer(byteBuffer); } public void close() throws IOException { fileChannel.close(); } public void next() throws IOException { checkPosition(position); ByteBuffer byteBuffer = ByteBuffer.allocate(1); readByteBuffer(byteBuffer); this.recordRemoved = (byteBuffer.array()[0] == '*'); for (Field field : fields) { read(field); } position++; } public boolean hasNext() { return position < header.getRecordCount(); } private void read(Field field) throws IOException { ByteBuffer buffer = ByteBuffer.allocate(field.getLength()); readByteBuffer(buffer); field.setStringValue(new String(buffer.array(), encode).trim()); field.setBuffer(buffer); } protected void readByteBuffer(ByteBuffer byteBuffer) throws IOException { fileChannel.read(byteBuffer); } } 这个类是最大的一个类,值得注意的是几个静态方法: addReader和parse,

addReader用于增加新的类型的Reader,parse用于解析文件。

parse的执行过程是首先读取第一个字节,判断是否有对应的解析实现类,如果有,就有对应的解析实现类去解析,如果没有,则抛出错误声明不支持。

下面写实现类就简单了,下面是FoxproDBase3的解析器:

public class FoxproDBase3Reader extends DbfReader {
    protected void readFields() throws IOException {
        fields = new ArrayList();
        for (int i = 0; i < (header.getHeaderLength() - 32 - 1) / 32; i++) {
            fields.add(readField());
        }
    }

    public byte getType() {
        return 3;
    }

    protected Field readField() throws IOException {
        Field field = new Field();
        ByteBuffer byteBuffer = ByteBuffer.allocate(32);
        readByteBuffer(byteBuffer);
        byte[] bytes = byteBuffer.array();
        field.setName(new String(bytes, 0, 11, encode).trim().split("\0")[0]);
        field.setType((char) bytes[11]);
        field.setDisplacement(Util.getUnsignedInt(bytes, 12, 4));
        field.setLength(Util.getUnsignedInt(bytes, 16, 1));
        field.setDecimal(Util.getUnsignedInt(bytes, 17, 1));
        field.setFlag(bytes[18]);
        return field;
    }

    protected void readHeader() throws IOException {
        header = new Header();
        ByteBuffer byteBuffer = ByteBuffer.allocate(31);
        readByteBuffer(byteBuffer);
        byte[] bytes = byteBuffer.array();
        header.setLastUpdate((Util.getUnsignedInt(bytes, 0, 1) + 1900) * 10000 + Util.getUnsignedInt(bytes, 1, 1) * 100 + Util.getUnsignedInt(bytes, 2, 1));
        header.setRecordCount(Util.getUnsignedInt(bytes, 3, 4));
        header.setHeaderLength(Util.getUnsignedInt(bytes, 7, 2));
        header.setRecordLength(Util.getUnsignedInt(bytes, 9, 2));
    }
}

测试用例

public class DbfReaderTest {
    static String[] files = {"BESTIMATE20140401", "BHDQUOTE20140401"};

    public static void main(String[] args) throws IOException, IllegalAccessException, InstantiationException {
        for (String file : files) {
            printFile(file);
        }
    }

    public static void printFile(String fileName) throws IOException, InstantiationException, IllegalAccessException {
        Reader dbfReader = DbfReader.parse("E:\\20140401\\" + fileName + ".DBF");
        for (Field field : dbfReader.getFields()) {
            System.out.printf("name:%s %s(%d,%d)\n", field.getName(), field.getType(), field.getLength(), field.getDecimal());
        }
        System.out.println();
        for (int i = 0; i < dbfReader.getHeader().getRecordCount(); i++) {
            dbfReader.next();
            for (Field field : dbfReader.getFields()) {
                System.out.printf("%" + field.getLength() + "s", field.getStringValue());
            }
            System.out.println();
        }
        dbfReader.close();

    }
}

可以看到最后的使用也是非常简洁的。

代码统计

\

总共的代码行数是282行,去掉import和接口声明之类的,真正干活的代码大概就200行了:

总结

上面不仅展示了如何实现DBF文件的解析,同时还展示了如何在现在面临的需求与未来的扩展进行合理均衡的设计方式。

比如:要实现另外一个标准的DBF文件支持,只要类似上面FoxproDBase3Reader类一样,简单实现之后,再调用DbfParser.addReader(xxxReader);

好的设计需要即避免过度设计,搞得太复杂,同时也要对未来的变化与扩展做适当考虑,避免新的需求来的时候需要这里动动,那里改改导致结构上的调整与变化,同时要注意遵守DRY原则,可以这样说如果程序中有必要的大量的重复,就说明一定存在结构设计上的问题。

所有的代码都可以在下面的连接看到:

https://code.csdn.net/tinygroup/tiny/tree/master/framework/org.tinygroup.dbf

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇PostgreSQL数据库远程连接功能的.. 下一篇Linux-6.5下基于MariaDB-10的主从..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: