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

📄 dbasereader.cs

📁 C# 的地图开发例子(sharp map)
💻 CS
📖 第 1 页 / 共 2 页
字号:
// 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("\0", "").Trim();				
				char fieldtype = br.ReadChar();
				switch (fieldtype)
				{
					case 'L':
						DbaseColumns[i].DataType = typeof(bool);
						break;
					case 'C':
						DbaseColumns[i].DataType = typeof(string);
						break;
					case 'D':
						DbaseColumns[i].DataType = typeof(DateTime);
						break;
					case 'N':
						DbaseColumns[i].DataType = typeof(double);
						break;
					case 'F':
						DbaseColumns[i].DataType = typeof(float);
						break;
					case 'B':
						DbaseColumns[i].DataType = typeof(byte[]);
						break;
					default:
						throw (new NotSupportedException("Invalid or unknown DBase field type '" + fieldtype +
								"' in column '" + DbaseColumns[i].ColumnName + "'"));
				}
				DbaseColumns[i].Address = br.ReadInt32();

				int Length = (int)br.ReadByte();
				if (Length < 0) Length = Length + 256;
				DbaseColumns[i].Length = Length;
				DbaseColumns[i].Decimals = (int)br.ReadByte();
				//If the double-type doesn't have any decimals, make the type an integer
				if (DbaseColumns[i].Decimals == 0 && DbaseColumns[i].DataType == typeof(double))
					if (DbaseColumns[i].Length <= 2)
						DbaseColumns[i].DataType = typeof(Int16);
					else if(DbaseColumns[i].Length<=4)
						DbaseColumns[i].DataType = typeof(Int32);
					else
						DbaseColumns[i].DataType = typeof(Int64);
				fs.Seek(fs.Position + 14, 0);
			}
			HeaderIsParsed = true;
			CreateBaseTable();
		}

		private System.Text.Encoding GetDbaseLanguageDriver(byte dbasecode)
		{
			switch (dbasecode)
			{
				case 0x01: return System.Text.Encoding.GetEncoding(437); //DOS USA code page 437 
				case 0x02: return System.Text.Encoding.GetEncoding(850); // DOS Multilingual code page 850 
				case 0x03: return System.Text.Encoding.GetEncoding(1252); // Windows ANSI code page 1252 
				case 0x04: return System.Text.Encoding.GetEncoding(10000); // Standard Macintosh 
				case 0x08: return System.Text.Encoding.GetEncoding(865); // Danish OEM
				case 0x09: return System.Text.Encoding.GetEncoding(437); // Dutch OEM
				case 0x0A: return System.Text.Encoding.GetEncoding(850); // Dutch OEM Secondary codepage
				case 0x0B: return System.Text.Encoding.GetEncoding(437); // Finnish OEM
				case 0x0D: return System.Text.Encoding.GetEncoding(437); // French OEM
				case 0x0E: return System.Text.Encoding.GetEncoding(850); // French OEM Secondary codepage
				case 0x0F: return System.Text.Encoding.GetEncoding(437); // German OEM
				case 0x10: return System.Text.Encoding.GetEncoding(850); // German OEM Secondary codepage
				case 0x11: return System.Text.Encoding.GetEncoding(437); // Italian OEM
				case 0x12: return System.Text.Encoding.GetEncoding(850); // Italian OEM Secondary codepage
				case 0x13: return System.Text.Encoding.GetEncoding(932); // Japanese Shift-JIS
				case 0x14: return System.Text.Encoding.GetEncoding(850); // Spanish OEM secondary codepage
				case 0x15: return System.Text.Encoding.GetEncoding(437); // Swedish OEM
				case 0x16: return System.Text.Encoding.GetEncoding(850); // Swedish OEM secondary codepage
				case 0x17: return System.Text.Encoding.GetEncoding(865); // Norwegian OEM
				case 0x18: return System.Text.Encoding.GetEncoding(437); // Spanish OEM
				case 0x19: return System.Text.Encoding.GetEncoding(437); // English OEM (Britain)
				case 0x1A: return System.Text.Encoding.GetEncoding(850); // English OEM (Britain) secondary codepage
				case 0x1B: return System.Text.Encoding.GetEncoding(437); // English OEM (U.S.)
				case 0x1C: return System.Text.Encoding.GetEncoding(863); // French OEM (Canada)
				case 0x1D: return System.Text.Encoding.GetEncoding(850); // French OEM secondary codepage
				case 0x1F: return System.Text.Encoding.GetEncoding(852); // Czech OEM
				case 0x22: return System.Text.Encoding.GetEncoding(852); // Hungarian OEM

⌨️ 快捷键说明

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