空间矢量数据(.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;
}
空间矢量数据(.shp文件)之JAVA操作的更多相关文章
- java操作office和pdf文件java读取word,excel和pdf文档内容
在平常应用程序中,对office和pdf文档进行读取数据是比较常见的功能,尤其在很多web应用程序中.所以今天我们就简单来看一下Java对word.excel.pdf文件的读取.本篇博客只是讲解简单应 ...
- Java IO_001.File类--文件或文件夹相关操作
Java IO之File对象常用操作 File类:用于文件或文件夹或网址相关联的操作.可以关联或不关联文件(即关联不存在的文件).构造函数有: public File(String pathname) ...
- java io流 对文件夹的操作
java io流 对文件夹的操作 检查文件夹是否存在 显示文件夹下面的文件 ....更多方法参考 http://www.cnblogs.com/phpyangbo/p/5965781.html ,与文 ...
- 【JAVA使用XPath、DOM4J解析XML文件,实现对XML文件的CRUD操作】
一.简介 1.使用XPath可以快速精确定位指定的节点,以实现对XML文件的CRUD操作. 2.去网上下载一个“XPath帮助文档”,以便于查看语法等详细信息,最好是那种有很多实例的那种. 3.学习X ...
- properties文件简介及其常用Java操作
一.properties文件简介 java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值&q ...
- Java操作文件夹的工具类
Java操作文件夹的工具类 import java.io.File; public class DeleteDirectory { /** * 删除单个文件 * @param fileName 要删除 ...
- Java操作属性文件,支持新增或更新多个属性
Java操作属性文件.支持新增或更新多个属性 一.更新或新增单个属性的方法 /** * 写入properties信息 * @param filePath 绝对路径(包含文件名称和后缀名) * @par ...
- JAVA操作properties文件
va中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式,在properties ...
- java文件的读写操作
java文件的读写操作主要是对输入流和输出流的操作,由于流的分类很多,所以概念很容易模糊,基于此,对于流的读写操作做一个小结. 1.根据数据的流向来分: 输出流:是用来写数据的,是由程序(内存)--- ...
随机推荐
- Lambda表达式-使用说明
jdk8已经发布4年,其中有一个特性:Lambda,它是一个令开发者便捷开发的一种方式,Lambda Expression (Lambda表达式)是为了让java提供一种面向函数编程,原本在jdk8之 ...
- 12.Intellij IDEA 添加jar包的三种方式
转自:https://blog.csdn.net/zwj1030711290/article/details/56678353/ 一.直接复制:(不推荐) 方法:直接将硬盘上的jar包复制粘贴到项目的 ...
- springboot shiro配置
导入相关包(这里配合使用Ehcache缓存) <dependency> <groupId>org.apache.shiro</groupId> <artifa ...
- LIMIT语句解析及本章简单回顾(二十九)
一.LIMIT 限制查询结果返回的数量 [LIMIT {[offset,] row_count | row_count OFFSET offset}] select * from user; 除了可以 ...
- Linux 下段错误 core文件
什么是core dump? core的意思是内存,dump的意思是扔出来,堆出来:当一个程序奔溃时,在进程当前工作目录的core文件中复制了该进程的存储图像.core文件仅仅是一个内存映像(同时加上调 ...
- jquery on event
<!doctype html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- ubuntu 18.04网卡命名规则改回传统的ethx
自15版本开始网卡命名规则就不叫eth0了.而是用可预期网络接口设备名称的命名规则,比如网卡名为enp3s0 . 如果想要变回ethx也是可以的,参考以下步骤: 1.编辑/etc/default/gr ...
- luogu-1908 逆序对 离散化+树状数组
题目链接:https://www.luogu.org/problem/show?pid=P1908 题意 简单的求逆序对 思路 用树状数组来做逆序对 对于过大的数字来讲,用离散化处理即可 比赛的时候没 ...
- java钩子函数
也不知道我理解的对不对,欢迎大家讨论! 自己写了个钩子函数,我理解的钩子函数: public interface Transactioner { String wedontknow() ; } pub ...
- 洛谷 P1454 圣诞夜的极光
P1454 圣诞夜的极光 题目背景 圣诞夜系列~~ 题目描述 圣诞老人回到了北极圣诞区,已经快到12点了.也就是说极光表演要开始了.这里的极光不是极地特有的自然极光景象.而是圣诞老人主持的人造极光. ...