空间矢量数据(.shp文件)之JAVA操作

Shape文件由ESRI开发,一个ESRI(Environmental Systems Research Institute)的shape文件包括一个主文件,一个索引文件,和一个dBASE表。其中主文件的后缀就是.shp。

Shape文件已经是一种开源的文件格式,官方早在2006年就出版了相应的白皮书,对整个文件的读写进行了详细的说明,这样也使得Shape文件应用的更加广泛。本人在移动GIS开发的过程中,借机对.shp文件进行了研究,并简单实现了通过JAVA语言对.shp文件的读写操作功能。

================================================ 我是分隔线==============================================

1、Shape文件

ESRI 的shape 文件由一个主文件、一个索引文件和一个dBASE 表构成。主文件是一个可变记录长度的随机文件,文件中的每个记录描述一个包含多个顶点的shape。在索引文件中,每个记录内容包含着与主文件中记录相对应的从主文件开始处的偏移量。dBASE
表中包含着与每个要素相对应的一条要素属性记录。几何数据与属性的一一对应关系是基于记录号来对应的。dBASE 文件中属性记录的顺序必须与主文件中的记录顺序相同。

详见白皮书。。。。。。。。。。。。。。。。。。。

2、java实现shape文件的读取

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.database.Cursor;
import android.os.Environment;
import android.widget.Toast;

public class ReadShapeFile_DAL {
	//分别用于存放shp文件和dbs文件,要求一一对应
	private  List<File> g_shpFileName;
	private  List<File> g_dbfFileName;
	private  List<VectorOcupy> g_shpAndDbfFiles;
    private  Activity g_at;
    private  String SDPATH;//离线矢量文件存储路径  

    public ReadShapeFile_DAL()
	{

	}

	public void SetSDPath(String _path)
	{
		SDPATH=_path;
	}

    /**
     * 判断机器中是否有存储卡
     * @return
     */
	private static boolean haveSDCARD() {
		String status = Environment.getExternalStorageState();
		if (status.equals(Environment.MEDIA_MOUNTED))
		{
			return true;
		}
		else
		{
			return false;
		}
	}

    //读取目录中的.shp和.dbf文件
	public  boolean ListFile(Activity _at)
	{
		boolean flag=false;
		g_at=_at;
		g_shpFileName=new ArrayList<File>();
		g_dbfFileName=new ArrayList<File>();
		g_shpAndDbfFiles=new ArrayList<VectorOcupy>();
		if(haveSDCARD()){
    		//得到当前外部存储设备的目录( /SDCARD )
			SDPATH = Environment.getExternalStorageDirectory() + "/LandMonitoringCollectionSystem";
    	}else{
    		//手机中文件放置路径
    		SDPATH = "/data/data/featuredata";
    	}
		try
		{
			File dirs = new File(SDPATH);
			File [] filenames=dirs.listFiles();
			if(filenames.length==0)
			{
				return flag;
			}
			else
			{
				for(int i =0;i<filenames.length;i++)
				{
					 File file = filenames[i];
					 if(file.isFile())
					 {
						 if(file.getName().endsWith(".shp"))
						 {
							 g_shpFileName.add(file);
						 }
						 else
						 {
							 if(file.getName().endsWith(".dbf"))
							 {
								 g_dbfFileName.add(file);
							 }
						 }
					 }
				  }
			}
			//判断矢量文件是否存在
			if(g_shpFileName.size()<1)
			{
				Toast.makeText(g_at, "数据读取失败,请确定离线数据存在",Toast.LENGTH_SHORT).show();
				return false;
			}
			else
			{
				g_shpAndDbfFiles=fileConfig(g_shpFileName,g_dbfFileName);
			}
			if(shpDataInsert())
			return true;
		}
		catch(Exception e)
		{
		   e.printStackTrace();
		   g_shpAndDbfFiles=new ArrayList<VectorOcupy>();
		   Toast.makeText(g_at,"数据读取失败,请确定离线数据存储的目录正确",Toast.LENGTH_SHORT).show();
		}
		return flag;
	}

	private  boolean shpDataInsert()
	{
		boolean flag=true;

		DataTableManagement g_myTableExcute=new DataTableManagement(g_at);
         //在此删除所有的矢量数据表
         String selectsql = "select * from sqlite_master"; 

     	 g_myTableExcute = new DataTableManagement(g_at);

			Cursor cs = g_myTableExcute.excuteCursorTable(selectsql);

			while(cs.moveToNext())
			{
				String tableName = cs.getString(cs.getColumnIndex("name"));
				if(tableName.contains("_shp"))
				{
					String str="DROP TABLE IF EXISTS "+tableName+";";
		  	    	g_myTableExcute.ExcuteTable(str);
				}
			}

		for(int i=0;i<g_shpAndDbfFiles.size();i++)
		{
			try
			{
				ReadShapeFile_Analysis myShapeFileAnalysis;
				/**
				 * 同时包含shp与dbf文件
				 */
				if(g_shpAndDbfFiles.get(i).getFlag())
				{
					myShapeFileAnalysis=new ReadShapeFile_Analysis(g_shpAndDbfFiles.get(i).getShpFile(),g_shpAndDbfFiles.get(i).getDbfFile(),g_at);
				}
				else
				{
					myShapeFileAnalysis=new ReadShapeFile_Analysis(g_shpAndDbfFiles.get(i).getShpFile(),g_at);
				}
				if(!myShapeFileAnalysis.read())
				flag=false;
				/*for(int j=0;j<dbfFileName.size();j++)
				{
					File dbfFile=dbfFileName.get(j);
					String filename=shpFileName.get(i).getName().substring(0, shpFileName.get(i).getName().lastIndexOf("."));
					if(dbfFile.getName().substring(0, dbfFile.getName().lastIndexOf(".")).equals(filename))
					{

					}
				}
				ShapeFileAnalysis myShapeFileAnalysis=new ShapeFileAnalysis(shpFileName.get(i),at);
				myShapeFileAnalysis.read();
				if(myShapeFileAnalysis.getifChanged())
				flag=true;*/
			}
			catch(Exception e)
			{
				e.printStackTrace();
				System.out.println("解析shapefile失败");
				flag=false;
			}
		}
		return flag;
	}

	private List<VectorOcupy> fileConfig(List<File> shpfiles,List<File> dbffiles)
	{
		List<VectorOcupy> vectorocupy=new ArrayList<VectorOcupy>();
		try
		{
			for(int i=0;i<shpfiles.size();i++)
			{
				boolean flag=false;
				for(int j=0;j<dbffiles.size();j++)
				{
					String filename=shpfiles.get(i).getName().substring(0, shpfiles.get(i).getName().lastIndexOf("."));
					if(dbffiles.get(j).getName().substring(0, dbffiles.get(j).getName().lastIndexOf(".")).equals(filename))
					{
						vectorocupy.add(new VectorOcupy(shpfiles.get(i),dbffiles.get(j),true));
						flag=true;
						break;
						//j=dbffiles.size();
					}
				}
				//针对只有.shp文件的数据
				if(flag == false)
				{
					vectorocupy.add(new VectorOcupy(shpfiles.get(i),false));
				}
			}
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return vectorocupy;
	}

	class VectorOcupy
	{
		private File shpdatafile;
		private File dbfdatafile;
		private boolean flag;

        public VectorOcupy(File shpfile,File dbffile,boolean flag)
		{
			this.flag=flag;
			this.dbfdatafile=dbffile;
			this.shpdatafile=shpfile;
		}

        public VectorOcupy(File shpfile,boolean flag)
		{
			this.flag=flag;
			this.shpdatafile=shpfile;
			this.dbfdatafile=null;
		}

        public File getShpFile()
		{
			return shpdatafile;
		}

        public File getDbfFile()
		{
			return dbfdatafile;
		}

        public boolean getFlag()
	    {
	    	return flag;
	    }
	}
}

3、DBF文件读取

package landmonitoring.mobilegismodels;

import java.io.*;

//Referenced classes of package cn.edu.sut.oa.workadmin.sjcl:
//             JDBFException, JDBField

public class DBFReader
{

     public DBFReader(String s)
         throws JDBFException
     {
         stream = null;
         fields = null;
         nextRecord = null;
         nFieldCount = 0;
         try
         {
             init(new FileInputStream(s));
         }
         catch(FileNotFoundException filenotfoundexception)
         {
             throw new JDBFException(filenotfoundexception);
         }
     }

     public DBFReader(FileInputStream inputstream)
         throws JDBFException
     {
         stream = null;
         fields = null;
         nextRecord = null;
         init(inputstream);
     }

     private void init(InputStream inputstream)
         throws JDBFException
     {
         try
         {
             stream = new DataInputStream(inputstream);
             int i = readHeader();
             fields = new JDBField[i];
             int j = 1;
             for(int k = 0; k < i; k++)
             {
                 fields[k] = readFieldHeader();
                 if(fields[k] != null)
                 {
                     nFieldCount++;
                     j += fields[k].getLength();
                 }
             }

             nextRecord = new byte[j];
             try
             {
                 stream.readFully(nextRecord);
             }
             catch(EOFException eofexception)
             {
                 nextRecord = null;
                 stream.close();
             }
             int l = 0;
             for(int i1 = 0; i1 < j; i1++)
             {
              if(nextRecord==null)
                     break;
              else
              {
                     if(nextRecord[i1] != 32 && nextRecord[i1] != 42)
                         continue;
                     l = i1;
                     break;
              }

             }

             if(l > 0)
             {
                 byte abyte0[] = new byte[l];
                 stream.readFully(abyte0);
                 for(int j1 = 0; j1 < j - l; j1++)
                     nextRecord[j1] = nextRecord[j1 + l];

                 for(int k1 = 0; k1 < l; k1++)
                     nextRecord[j - k1 - 1] = abyte0[l - k1 - 1];

             }
         }
         catch(IOException ioexception)
         {
             throw new JDBFException(ioexception);
         }
     }

     private int readHeader()
         throws IOException, JDBFException
     {
         byte abyte0[] = new byte[16];
         try
         {
             stream.readFully(abyte0);
         }
         catch(EOFException eofexception)
         {
             throw new JDBFException("Unexpected end of file reached.");
         }
         int i = abyte0[8];
         if(i < 0)
             i += 256;
         i += 256 * abyte0[9];
         i = --i / 32;
         i--;
         try
         {
             stream.readFully(abyte0);
         }
         catch(EOFException eofexception1)
         {
             throw new JDBFException("Unexpected end of file reached.");
         }
         return i;
     }

     private JDBField readFieldHeader()
         throws IOException, JDBFException
     {
         byte abyte0[] = new byte[16];
         try
         {
             stream.readFully(abyte0);
         }
         catch(EOFException eofexception)
         {
             throw new JDBFException("Unexpected end of file reached.");
         }
         if(abyte0[0] == 13 || abyte0[0] == 0)
         {
             stream.readFully(abyte0);
             return null;
         }
         StringBuffer stringbuffer = new StringBuffer(10);
         int i = 0;
         for(i = 0; i < 10; i++)
             if(abyte0[i] == 0)
                 break;

         stringbuffer.append(new String(abyte0, 0, i,"GB2312"));
         char c = (char)abyte0[11];
         try
         {
             stream.readFully(abyte0);
         }
         catch(EOFException eofexception1)
         {
             throw new JDBFException("Unexpected end of file reached.");
         }
         int j = abyte0[0];
         int k = abyte0[1];
         if(j < 0)
             j += 256;
         if(k < 0)
             k += 256;
         return new JDBField(stringbuffer.toString(), c, j, k);
     }

     public int getFieldCount()
     {
         return nFieldCount;
     }

     public JDBField getField(int i)
     {
         return fields[i];
     }

     public boolean hasNextRecord()
     {
         return nextRecord != null;
     }

     public Object[] nextRecord()
         throws JDBFException
     {
         if(!hasNextRecord())
             throw new JDBFException("No more records available.");
         Object aobj[] = new Object[nFieldCount];
         int i = 1;
         for(int j = 0; j < aobj.length; j++)
         {
             int k = fields[j].getLength();
             StringBuffer stringbuffer = new StringBuffer(k);
             try {
				stringbuffer.append(new String(nextRecord, i, k,"GB2312"));
				aobj[j] = fields[j].parse(stringbuffer.toString());
	             i += fields[j].getLength();
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
         }

         try
         {
             stream.readFully(nextRecord);
         }
         catch(EOFException eofexception)
         {
             nextRecord = null;
         }
         catch(IOException ioexception)
         {
             throw new JDBFException(ioexception);
         }
         return aobj;
     }

     public String[] nextRecordString()
         throws JDBFException
     {
         if(!hasNextRecord())
             throw new JDBFException("No more records available.");
         String as[] = new String[nFieldCount];
         int i = 1;
         for(int j = 0; j < as.length; j++)
         {
             int k = fields[j].getLength();
             StringBuffer stringbuffer = new StringBuffer(k);

             try {
            	 stringbuffer.append(new String(nextRecord, i, k,"GB2312"));
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
             as[j] = stringbuffer.toString();
             i += fields[j].getLength();
         }

         try
         {
             stream.readFully(nextRecord);
         }
         catch(EOFException eofexception)
         {
             nextRecord = null;
         }
         catch(IOException ioexception)
         {
             throw new JDBFException(ioexception);
         }
         return as;
     }

     public void close()
         throws JDBFException
     {
         nextRecord = null;
         try
         {
             stream.close();
         }
         catch(IOException ioexception)
         {
             throw new JDBFException(ioexception);
         }
     }

     private DataInputStream stream;
     private JDBField fields[];
     private byte nextRecord[];
     private int nFieldCount;
}

4、DBF写入

package landmonitoring.mobilegismodels;

import java.io.*;
import java.util.Calendar;

public class DBFWriter
{

       public DBFWriter(String s, JDBField ajdbfield[])
           throws JDBFException
       {
           stream = null;
           recCount = 0;
           fields = null;
           fileName = null;
           dbfEncoding = null;
           fileName = s;
           try
           {
               init(new FileOutputStream(s), ajdbfield);
           }
           catch(FileNotFoundException filenotfoundexception)
           {
               throw new JDBFException(filenotfoundexception);
           }
       }

       public DBFWriter(OutputStream outputstream, JDBField ajdbfield[])
           throws JDBFException
       {
           stream = null;
           recCount = 0;
           fields = null;
           fileName = null;
           dbfEncoding = null;
           init(outputstream, ajdbfield);
       }

       public DBFWriter(String s, JDBField ajdbfield[], String s1)
           throws JDBFException
       {
           stream = null;
           recCount = 0;
           fields = null;
           fileName = null;
           dbfEncoding = null;
           fileName = s;
           try
           {
               dbfEncoding = s1;
               init(new FileOutputStream(s), ajdbfield);
           }
           catch(FileNotFoundException filenotfoundexception)
           {
               throw new JDBFException(filenotfoundexception);
           }
       }

       private void init(OutputStream outputstream, JDBField ajdbfield[])
           throws JDBFException
       {
           fields = ajdbfield;
           try
           {
               stream = new BufferedOutputStream(outputstream);
               writeHeader();
               for(int i = 0; i < ajdbfield.length; i++)
                   writeFieldHeader(ajdbfield[i]);

               stream.write(13);
               stream.flush();
           }
           catch(Exception exception)
           {
               throw new JDBFException(exception);
           }
       }

       private void writeHeader()
           throws IOException
       {
           byte abyte0[] = new byte[16];
           abyte0[0] = 3;
           Calendar calendar = Calendar.getInstance();
           abyte0[1] = (byte)(calendar.get(1) - 1900);
           abyte0[2] = (byte)calendar.get(2);
           abyte0[3] = (byte)calendar.get(5);
           abyte0[4] = 0;
           abyte0[5] = 0;
           abyte0[6] = 0;
           abyte0[7] = 0;
           int i = (fields.length + 1) * 32 + 1;
           abyte0[8] = (byte)(i % 256);
           abyte0[9] = (byte)(i / 256);
           int j = 1;
           for(int k = 0; k < fields.length; k++)
               j += fields[k].getLength();

           abyte0[10] = (byte)(j % 256);
           abyte0[11] = (byte)(j / 256);
           abyte0[12] = 0;
           abyte0[13] = 0;
           abyte0[14] = 0;
           abyte0[15] = 0;
           stream.write(abyte0, 0, abyte0.length);
           for(int l = 0; l < 16; l++)
               abyte0[l] = 0;

           stream.write(abyte0, 0, abyte0.length);
       }

       private void writeFieldHeader(JDBField jdbfield)
           throws IOException
       {
           byte abyte0[] = new byte[16];
           /*定义一个新数组,用来接收新构造的字符串字节数组*/
           byte abytem[];
           String s = jdbfield.getName();
           String news = new String();

           int j = 0;
           /*循环从新组成字符串,此字符串的字节长度不能大于10*/
           for(int k = 0; k<s.length();k++)
           {
            if((s.substring(k,k+1).getBytes().length+j)>10) /*字节长度大于1的时候为汉字*/
            {
             break;
            }
            else
            {
              j = j + s.substring(k,k+1).getBytes().length;
              news = news + s.charAt(k);
            }
           }

           /*接收字节数组*/
           abytem = news.getBytes();
           /*将字数组数据合并到文件头数据组*/
           for(int k = 0; k<abytem.length;k++)
           {
            abyte0[k] = abytem[k];
           }
           /*在没有地方补空*/
           for(int k = j; k <= 10; k++)
             abyte0[k] = 0;

           abyte0[11] = (byte)jdbfield.getType();
           abyte0[12] = 0;
           abyte0[13] = 0;
           abyte0[14] = 0;
           abyte0[15] = 0;

           stream.write(abyte0, 0, abyte0.length);

           for(int l = 0; l < 16; l++)
               abyte0[l] = 0;

           abyte0[0] = (byte)jdbfield.getLength();
           abyte0[1] = (byte)jdbfield.getDecimalCount();
           stream.write(abyte0, 0, abyte0.length);
       }

       public void addRecord(Object aobj[])
           throws JDBFException
       {
           if(aobj.length != fields.length)
               throw new JDBFException("Error adding record: Wrong number of values. Expected " + fields.length + ", got " + aobj.length + ".");
           int i = 0;
           for(int j = 0; j < fields.length; j++)
               i += fields[j].getLength();

           byte abyte0[] = new byte[i];
           int k = 0;
           for(int l = 0; l < fields.length; l++)
           {
               String s = fields[l].format(aobj[l]);
               byte abyte1[];
               try
               {
                   if(dbfEncoding != null)
                       abyte1 = s.getBytes(dbfEncoding);
                   else
                       abyte1 = s.getBytes();
               }
               catch(UnsupportedEncodingException unsupportedencodingexception)
               {
                   throw new JDBFException(unsupportedencodingexception);
               }
               for(int i1 = 0; i1 < fields[l].getLength(); i1++)
                   abyte0[k + i1] = abyte1[i1];

               k += fields[l].getLength();
           }

           try
           {
               stream.write(32);
               stream.write(abyte0, 0, abyte0.length);
               stream.flush();
           }
           catch(IOException ioexception)
           {
               throw new JDBFException(ioexception);
           }
           recCount++;
       }

       public void close()
           throws JDBFException
       {
           try
           {
               stream.write(26);
               stream.close();
               RandomAccessFile randomaccessfile = new RandomAccessFile(fileName, "rw");
               randomaccessfile.seek(4L);
               byte abyte0[] = new byte[4];
               abyte0[0] = (byte)(recCount % 256);
               abyte0[1] = (byte)((recCount / 256) % 256);
               abyte0[2] = (byte)((recCount / 0x10000) % 256);
               abyte0[3] = (byte)((recCount / 0x1000000) % 256);
               randomaccessfile.write(abyte0, 0, abyte0.length);
               randomaccessfile.close();
           }
           catch(IOException ioexception)
           {
               throw new JDBFException(ioexception);
           }
       }

       private BufferedOutputStream stream;
       private int recCount;
       private JDBField fields[];
       private String fileName;
       private String dbfEncoding;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-19 22:28:29

空间矢量数据(.shp文件)之JAVA操作的相关文章

java操作office和pdf文件java读取word,excel和pdf文档内容

在平常应用程序中,对office和pdf文档进行读取数据是比较常见的功能,尤其在很多web应用程序中.所以今天我们就简单来看一下Java对word.excel.pdf文件的读取.本篇博客只是讲解简单应用.如果想深入了解原理.请读者自行研究一些相关源码. 首先我们来认识一下读取相关文档的jar包: 1. 引用POI包读取word文档内容 poi.jar 下载地址 http://apache.freelamp.com/poi/release/bin/poi-bin-3.6-20091214.zip 

【Java】利用文件输入输出流完成把一个文件夹内的所有文件拷贝的另一的文件夹的操作

一.基本目标 使用Java完成如下的操作: 把一个文件夹内的所有文件拷贝的另一的文件夹,例如,在F盘中有a与b两个文件夹: f:/a里面有一堆文件,运行Java程序之后就会全部复制到f:/b,并且完成重命名,在所有文件之前加rename_的前缀,如果里面有文件夹,则文件夹不重命名,里面的文件进行重命名,同样在所有文件之前加rename_的前缀: 二.制作过程 1.首先主函数非常简单,就是调用了上面FileTest类中的copyFolder函数 public class FileCopy { pu

JAVA操作properties文件

java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式,在properties文件中,可以用"#"来作注释,properties文件在Java编程中用到的地方很多,操作很方便.一.properties文件test.properties------------------------------------------------------###########

properties文件简介及其常用Java操作

一.properties文件简介 java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"(推荐)或"键:值"的格式,在properties文件中,可以用"#"(推荐)或者"//"来作注释,properties文件在Java编程中用到的地方很多,操作很方便. 现在定义一个databaseInfo.properties文件,如下:#

java io流 对文件夹的操作

检查文件夹是否存在 显示文件夹下面的文件 ....更多方法参考 http://www.cnblogs.com/phpyangbo/p/5965781.html ,与文件操作方法通用,因为都是一个类 //对文件夹的操作 //检查文件夹是否存在 //显示文件夹下面的文件 //.... import java.io.*; import java.util.*; public class Index{ public static void main(String[] args) throws Excep

(IO流)java中多种方式读文件,追加文件内容,对文件的各种操作

import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.io.R

Java操作读取写入文本TXT及XML文件内容

package fileIo; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; public class ReadTextFile { public BufferedReader bufread; public BufferedWriter bufwriter; File

java操作properties文件简单学习

java操作properties文件的工具类简单封装: 注意:由于本地和环境和linux服务的路径有区别,或者jetty,resin,tomcat部署后,文件的路径也是有区别的.比如我们在linux上把项目放在另一个磁盘下,此时,文件的路径就是项目所在的路径,而不是WEB-INF下,所以,这里需要灵活配置! package com.sohu.util; import java.io.BufferedInputStream; import java.io.File; import java.io.

Java操作属性文件,支持新增或更新多个属性

Java操作属性文件,支持新增或更新多个属性 一.更新或新增单个属性的方法 /** * 写入properties信息 * @param filePath 绝对路径(包括文件名和后缀名) * @param parameterName 名称 * @param parameterValue 值 */ public static void writeProperties(String filePath, String parameterName, String parameterValue) { Pro