DbaseReader.cs
上传用户:sex100000
上传日期:2013-11-09
资源大小:1377k
文件大小:20k
- // Copyright 2005, 2006 - Morten Nielsen (www.iter.dk)
- //
- // This file is part of SharpMap.
- // SharpMap 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 of the License, or
- // (at your option) any later version.
- //
- // SharpMap 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.
- // You should have received a copy of the GNU Lesser General Public License
- // along with SharpMap; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- // Note:
- // Good stuff on DBase format: http://www.clicketyclick.dk/databases/xbase/format/
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.IO;
- using System.Data;
- namespace SharpMap.Data.Providers
- {
- internal class DbaseReader : IDisposable
- {
- private struct DbaseField
- {
- public string ColumnName;
- public Type DataType;
- public int Address;
- public int Length;
- public int Decimals;
-
- }
-
- private DateTime _lastUpdate;
- private int _NumberOfRecords;
- private Int16 _HeaderLength;
- private Int16 _RecordLength;
- private string _filename;
- private DbaseField[] DbaseColumns;
- private FileStream fs;
- private BinaryReader br;
- private bool HeaderIsParsed;
-
- public DbaseReader(string filename)
- {
-
- if (!File.Exists(filename))
- throw new FileNotFoundException(String.Format("Could not find file "{0}"", filename));
- _filename = filename;
- HeaderIsParsed = false;
- }
- private bool _isOpen;
- public bool IsOpen
- {
- get { return _isOpen; }
- set { _isOpen = value; }
- }
-
- public void Open()
- {
- fs = new FileStream(_filename, FileMode.Open, FileAccess.Read);
- br = new BinaryReader(fs);
- _isOpen = true;
- if (!HeaderIsParsed) //Don't read the header if it's already parsed
- ParseDbfHeader(_filename);
- }
- public void Close()
- {
- br.Close();
- fs.Close();
- _isOpen = false;
- }
- public void Dispose()
- {
- if(_isOpen)
- this.Close();
- br = null;
- fs = null;
- }
- // Binary Tree not working yet on Mono
- // see bug: http://bugzilla.ximian.com/show_bug.cgi?id=78502
- #if !MONO
- /// <summary>
- /// Indexes a DBF column in a binary tree [NOT COMPLETE]
- /// </summary>
- /// <typeparam name="T">datatype to be indexed</typeparam>
- /// <param name="ColumnId">Column to index</param>
- /// <returns></returns>
- public SharpMap.Utilities.Indexing.BinaryTree<T, UInt32> CreateDbfIndex<T>(int ColumnId) where T:IComparable<T>
- {
- SharpMap.Utilities.Indexing.BinaryTree<T, UInt32> tree = new SharpMap.Utilities.Indexing.BinaryTree<T, uint>();
- for (uint i = 0; i < ((this._NumberOfRecords>10000)?10000:this._NumberOfRecords); i++)
- tree.Add(new SharpMap.Utilities.Indexing.BinaryTree<T, uint>.ItemValue((T)GetValue(i, ColumnId), i));
- return tree;
- }
- #endif
- /*
- /// <summary>
- /// Creates an index on the columns for faster searching [EXPERIMENTAL - Requires Lucene dependencies]
- /// </summary>
- /// <returns></returns>
- public string CreateLuceneIndex()
- {
- string dir = this._filename + ".idx";
- if (!System.IO.Directory.Exists(dir))
- System.IO.Directory.CreateDirectory(dir);
- Lucene.Net.Index.IndexWriter iw = new Lucene.Net.Index.IndexWriter(dir,new Lucene.Net.Analysis.Standard.StandardAnalyzer(),true);
- for (uint i = 0; i < this._NumberOfRecords; i++)
- {
- FeatureDataRow dr = GetFeature(i,this.NewTable);
- Lucene.Net.Documents.Document doc = new Lucene.Net.Documents.Document();
- // Add the object-id as a field, so that index can be maintained.
- // This field is not stored with document, it is indexed, but it is not
- // tokenized prior to indexing.
- //doc.Add(Lucene.Net.Documents.Field.UnIndexed("SharpMap_oid", i.ToString())); //Add OID index
- foreach(System.Data.DataColumn col in dr.Table.Columns) //Add and index values from DBF
- {
- if(col.DataType.Equals(typeof(string)))
- // Add the contents as a valued Text field so it will get tokenized and indexed.
- doc.Add(Lucene.Net.Documents.Field.UnStored(col.ColumnName,(string)dr[col]));
- else
- doc.Add(Lucene.Net.Documents.Field.UnStored(col.ColumnName, dr[col].ToString()));
- }
- iw.AddDocument(doc);
- }
- iw.Optimize();
- iw.Close();
- return this._filename + ".idx";
- }
- */
- /// <summary>
- /// Gets the date this file was last updated.
- /// </summary>
- public DateTime LastUpdate
- {
- get { return _lastUpdate; }
- }
-
- private void ParseDbfHeader(string filename)
- {
- if (br.ReadByte() != 0x03)
- throw new NotSupportedException("Unsupported DBF Type");
-
- _lastUpdate = new DateTime((int)br.ReadByte() + 1900, (int)br.ReadByte(), (int)br.ReadByte()); //Read the last update date
- _NumberOfRecords = br.ReadInt32(); // read number of records.
- _HeaderLength = br.ReadInt16(); // read length of header structure.
- _RecordLength = br.ReadInt16(); // read length of a record
- fs.Seek(29, SeekOrigin.Begin); //Seek to encoding flag
- _FileEncoding = GetDbaseLanguageDriver(br.ReadByte()); //Read and parse Language driver
- fs.Seek(32, SeekOrigin.Begin); //Move past the reserved bytes
- int NumberOfColumns = (_HeaderLength - 31) / 32; // calculate the number of DataColumns in the header
- DbaseColumns = new DbaseField[NumberOfColumns];
- for (int i = 0; i < DbaseColumns.Length;i++)
- {
- DbaseColumns[i] = new DbaseField();
- DbaseColumns[i].ColumnName = System.Text.Encoding.UTF7.GetString((br.ReadBytes(11))).Replace("