1 概述
目前ArcGIS的切片格式目前主要可以分为三种形式,松散型切片格式,紧凑型切片格式和紧凑型2.0数据格式。
2 松散型切片格式
第一个比例尺的文件夹名为L00,第二个比例尺的为L01,如此类推。比例尺文件夹(一下统称L文件夹)目录下还会有R开头的文件夹,R表示的ROW,当前比例尺的瓦片每一行对应一个文件夹。R文件夹的命名方式是瓦片的行序列(用rIndex表示),把rIndex转为8位16进制,不足的在左边补0,用代码公式表示FolderName = “R”+rIndex.ToString(“x”).PadLeft(8, ‘0’) 。R文件夹里面保存的就是瓦片,瓦片的命名方式跟R文件夹的命名方式相似,以字母C开头,后面是瓦片在该行的列序号(用cIndex)表示,后面依然是一个8位16进制FileName = “C”+rIndex.ToString(“x”).PadLeft(8, ‘0’)+ “.”+format.ToString()。
3 紧凑型切片格式
紧凑型切片格式(暂且把它叫做1.0格式),在切片方案文件conf.xml中,对应节点标识如下:
<CacheStorageInfo xsi:type="typens:CacheStorageInfo">
<StorageFormat>esriMapCacheStorageModeCompact</StorageFormat>
<PacketSize>128</PacketSize>
</CacheStorageInfo>
包含了两类文件,bundle和bundlex,其中bundle文件中存储的是图片文件,bundlx文件中则存储了各个图片文件在bundle文件中的偏移量。
4 紧凑型切片2.0格式
紧凑型切片2.0格式,在切片方案文件conf.xml中,对应节点标识如下:
<CacheStorageInfo xsi:type="typens:CacheStorageInfo">
<StorageFormat>esriMapCacheStorageModeCompactV2</StorageFormat>
<PacketSize>128</PacketSize>
</CacheStorageInfo>
相比较与1.0的格式,缓存文件夹下仅包含了bundle文件
以下代码为读取松散型数据格式和紧凑型1.0数据格式的,2.0格式的读取方式后面更新。
class GetTileBytesHandle
{
/// <summary>
/// 从本地切片文件读取相应的层行列对应的切片
/// </summary>
/// <param name="level"></param>
/// <param name="row"></param>
/// <param name="column"></param>
/// <returns></returns>
public byte[] GetTileBytesExplores(int level, int row, int column)
{
try
{
string bundlesDir = input_path + "\\_alllayers";
string l = "0" + level;
int lLength = l.Length;
if (lLength > 2)
{
l = l.Substring(lLength - 2);
}
l = "L" + l;
//int rGroup = size * (row / size);
string r = "0000000" + row.ToString("X");
int rLength = r.Length;
if (rLength > 8)
{
r = r.Substring(rLength - 8);
}
r = "R" + r;
//int cGroup = size * (column / size);
string c = "0000000" + column.ToString("X");
int cLength = c.Length;
if (cLength > 8)
{
c = c.Substring(cLength - 8);
}
c = "C" + c;
string bundleBase = bundlesDir + "\\" + l + "\\" + r + "\\" + c + ".png";
if (File.Exists(bundleBase))
{
return GetFileStream(bundleBase);
}
else
return null;
}
catch (System.Exception ex)
{
return null;
}
}
/// <summary>
/// 从本地切片文件读取相应的层行列对应的切片
/// </summary>
/// <param name="level"></param>
/// <param name="row"></param>
/// <param name="column"></param>
/// <returns></returns>
public byte[] GetTileBytesDot3(int mLevel, int mRow, int mColumn)
{
int size = 128;
//byte[] result = null;
byte[] tileBytes = null;
FileStream isBundle = null;
string bundlesDir = input_path + "\\_alllayers";
try
{
string level = mLevel.ToString();
int levelLength = level.Length;
if (levelLength == 1)
{
level = "0" + level;
}
level = "L" + level;
int rowGroup = 128 * (mRow / 128);
string row = rowGroup.ToString("X");
int rowLength = row.Length;
if (rowLength < 4)
{
for (int i = 0; i < 4 - rowLength; i++)
{
row = "0" + row;
}
}
row = "R" + row;
int columnGroup = 128 * (mColumn / 128);
string column = columnGroup.ToString("X");
int columnLength = column.Length;
if (columnLength < 4)
{
for (int i = 0; i < 4 - columnLength; i++)
{
column = "0" + column;
}
}
column = "C" + column;
//string bundleName = string.Format("%S/%S/%S%S", bundlesDir, level, row, column) + ".bundle";
string bundleName = bundlesDir + "\\" + level + "\\" + row + column + ".bundle";
int index = 128 * (mRow - rowGroup) + (mColumn - columnGroup);
//isBundle = new RandomAccessFile(bundleName, "r");
//isBundle.skipBytes(64 + 8*index);
if (!File.Exists(bundleName) )
return null;
isBundle = new FileStream(bundleName, FileMode.Open, FileAccess.Read);
isBundle.Seek(64 + 8 * index, SeekOrigin.Begin);
//获取位置索引并计算切片位置偏移量
byte[] indexBytes = new byte[4];
isBundle.Read(indexBytes, 0, 4);
long offset = (long)(indexBytes[0] & 0xff) + (long)(indexBytes[1] & 0xff) * 256 + (long)(indexBytes[2] & 0xff) * 65536
+ (long)(indexBytes[3] & 0xff) * 16777216;
//获取切片长度索引并计算切片长度
long startOffset = offset - 4;
isBundle.Seek(startOffset, SeekOrigin.Begin);
byte[] lengthBytes = new byte[4];
isBundle.Read(lengthBytes, 0, 4);
int length = (int)(lengthBytes[0] & 0xff) + (int)(lengthBytes[1] & 0xff) * 256 + (int)(lengthBytes[2] & 0xff) * 65536
+ (int)(lengthBytes[3] & 0xff) * 16777216;
//根据切片位置和切片长度获取切片
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
tileBytes = new byte[length];
int bytesRead = 0;
if (length > 4)
{
bytesRead = isBundle.Read(tileBytes, 0, tileBytes.Length);
}
else
{
tileBytes = null;
}
//tile = bos.toByteArray();
}
catch (Exception ex)
{
return null;
}
finally
{
if (isBundle != null)
{
isBundle.Close();
}
}
return tileBytes;
}
/// <summary>
/// 从本地切片文件读取相应的层行列对应的切片
/// </summary>
/// <param name="level"></param>
/// <param name="row"></param>
/// <param name="column"></param>
/// <returns></returns>
public byte[] GetTileBytes(int level, int row, int column)
{
int size = 128;
byte[] result = null;
FileStream isBundle = null;
FileStream isBundlx = null;
try
{
string bundlesDir = input_path + "\\_alllayers";
string l = "0" + level;
int lLength = l.Length;
if (lLength > 2)
{
l = l.Substring(lLength - 2);
}
l = "L" + l;
int rGroup = size * (row / size);
string rGroupString = rGroup.ToString("X");
string r;
if (rGroupString.Length <= 4)
{
r = "000" + rGroup.ToString("X");
int rLength = r.Length;
if (rLength > 4)
{
r = r.Substring(rLength - 4);
}
}
else
{
r = rGroupString;
}
r = "R" + r;
int cGroup = size * (column / size);
string cGroupString = cGroup.ToString("X");
string c;
if (cGroupString.Length <= 4)
{
c = "000" + cGroup.ToString("X");
int rLength = c.Length;
if (rLength > 4)
{
c = c.Substring(rLength - 4);
}
}
else
{
c = cGroupString;
}
c = "C" + c;
string bundleBase = bundlesDir + "\\" + l + "\\" + r + c;
string bundlxFileName = bundleBase + ".bundlx";
string bundleFileName = bundleBase + ".bundle";
if (!File.Exists(bundlxFileName) || !File.Exists(bundleFileName))
return null;
int index = size * (column - cGroup) + (row - rGroup);
//行列号是整个范围内的,在某个文件中需要先减去前面文件所占有的行列号(都是128的整数)这样就得到在文件中的真是行列号
isBundlx = new FileStream(bundlxFileName, FileMode.Open, FileAccess.Read);
isBundlx.Seek(16 + 5 * index, SeekOrigin.Begin);
byte[] buffer = new byte[5];
isBundlx.Read(buffer, 0, 5);
long offset = (long)(buffer[0] & 0xff) + (long)(buffer[1] & 0xff) * 256 +
(long)(buffer[2] & 0xff) * 65536 + (long)(buffer[3] & 0xff) * 16777216 +
(long)(buffer[4] & 0xff) * 4294967296L;
isBundle = new FileStream(bundleFileName, FileMode.Open, FileAccess.Read);
isBundle.Seek(offset, SeekOrigin.Begin);
byte[] lengthBytes = new byte[4];
isBundle.Read(lengthBytes, 0, 4);
int length = (int)(lengthBytes[0] & 0xff)
+ (int)(lengthBytes[1] & 0xff) * 256
+ (int)(lengthBytes[2] & 0xff) * 65536
+ (int)(lengthBytes[3] & 0xff) * 16777216;
result = new byte[length];
isBundle.Read(result, 0, length);
}
catch (Exception ex)
{
return null;
}
finally
{
if (isBundle != null)
{
isBundle.Close();
isBundlx.Close();
}
}
return result;
}
}