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 Listg_shpFileName; private List g_dbfFileName; private List 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 (); g_dbfFileName=new ArrayList (); g_shpAndDbfFiles=new ArrayList (); 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 (); 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 fileConfig(List shpfiles,List dbffiles) { List vectorocupy=new ArrayList (); try { for(int i=0;i
3、DBF文件读取
package landmonitoring.mobilegismodels;import java.io.*;//Referenced classes of package cn.edu.sut.oa.workadmin.sjcl:// JDBFException, JDBFieldpublic 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; k10) /*字节长度大于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