2006-08-23

Geoserver解决shapefile中文问题

http://mycsoft.spaces.live.com/Blog/cns!97F5FD63B912AE58!555.entry

June 16
Geoserver解决shapefile中文问题
将以下文件重新编译.替换掉lib/gt2-shapefile.jar类库中的对应class文件.
如果是用GeoTools,不用改文件.可以通过重载的方式实现对中文正确的解读.

======================================================

/*
* Geotools - OpenSource mapping toolkit
* (C) 2002, Centre for Computational Geography
*
* This library 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;
* version 2.1 of the License.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This file is based on an origional contained in the GISToolkit project:
* http://gistoolkit.sourceforge.net/
*
*/
package org.geotools.data.shapefile.dbf;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Calendar;
import org.geotools.data.shapefile.StreamLogging;
import org.geotools.resources.NIOUtilities;
import org.geotools.resources.NumberParser;
/**
* A DbaseFileReader is used to read a dbase III format file.

* The general use of this class is:

*
* FileChannel in = new FileInputStream("thefile.dbf").getChannel();
* DbaseFileReader r = new DbaseFileReader( in ) Object[] fields = new
* Object[r.getHeader().getNumFields()]; while (r.hasNext()) {
* r.readEntry(fields); // do stuff } r.close();
*
*
For consumers who wish to be a bit more selective with their reading
* of rows, the Row object has been added. The semantics are the same as using
* the readEntry method, but remember that the Row object is always the same.
* The values are parsed as they are read, so it pays to copy them out (as each
* call to Row.read() will result in an expensive String parse).

* EACH CALL TO readEntry OR readRow ADVANCES THE FILE!

* An example of using the Row method of reading:

*
* FileChannel in = new FileInputStream("thefile.dbf").getChannel();
* DbaseFileReader r = new DbaseFileReader( in ) int fields =
* r.getHeader().getNumFields(); while (r.hasNext()) { DbaseFileReader.Row row =
* r.readRow(); for (int i = 0; i <>
*
* @author Michael Ma Ian Schneider
*
* @source $URL: http://svn.geotools.org/geotools/tags/2.2-RC3/plugin/shapefile/src/org/geotools/data/shapefile/dbf/DbaseFileReader.java $
*/
public class DbaseFileReader {
public final class Row {
public Object read(int column) throws IOException {
int offset = getOffset(column);
return readObject(offset, column);
}
public String toString() {
StringBuffer ret = new StringBuffer("DBF Row - ");
for (int i = 0; i < cnt =" 1;" numberparser =" new" currentoffset =" 0;" streamlogger="new" channel =" channel;" usememorymappedbuffer =" useMemoryMappedBuffer;" randomaccessenabled =" (channel" header =" new" r =" buffer.remaining();"> 0 &&amp; r != -1) {
r = channel.read(buffer);
}
if (r == -1) {
buffer.limit(buffer.position());
}
return r;
}
private void bufferCheck() throws IOException {
// remaining is less than record length
// compact the remaining data and read again
if (!buffer.isReadOnly()
&& buffer.remaining() < offset =" 0;" i =" 0," ii =" column;" fc =" (FileChannel)" buffer =" fc.map(FileChannel.MapMode.READ_ONLY," currentoffset =" 0;" usememorymappedbuffer =" false;" size =" 8" size =" header.getRecordLength()"> size ? header.getRecordLength()
: size;
buffer = ByteBuffer.allocateDirect(size);
// fill it and reset
fill(buffer, channel);
buffer.flip();
this.currentOffset = header.getHeaderLength();
}
// The entire file is in little endian
buffer.order(ByteOrder.LITTLE_ENDIAN);
// Set up some buffers and lookups for efficiency
fieldTypes = new char[header.getNumFields()];
fieldLengths = new int[header.getNumFields()];
for (int i = 0, ii = header.getNumFields(); i < charbuffer =" CharBuffer.allocate(header.getRecordLength()" chars =" Charset.forName(" decoder =" chars.newDecoder();" row =" new">Highly recomended.
*
* @throws IOException
* If an error occurs.
*/
public void close() throws IOException {
if (channel.isOpen()) {
channel.close();
streamLogger.close();
}
if (buffer instanceof MappedByteBuffer) {
NIOUtilities.clean(buffer);
}

buffer = null;
channel = null;
charBuffer = null;
decoder = null;
header = null;
row = null;
}
/**
* Query the reader as to whether there is another record.
*
* @return True if more records exist, false otherwise.
*/
public boolean hasNext() {
return cnt < foundrecord =" false;" tempdeleted =" (char)" foundrecord =" true;" numfields =" header.getNumFields();" fieldoffset =" 0;" j =" 0;" foundrecord =" false;" deleted =" (char)" deleted ="=" foundrecord =" true;" type =" fieldTypes[fieldNum];" fieldlen =" fieldLengths[fieldNum];" object =" null;"> 0) {
switch (type) {
// (L)logical (T,t,F,f,Y,y,N,n)
case 'l':
case 'L':
switch (charBuffer.charAt(fieldOffset)) {
case 't':
case 'T':
case 'Y':
case 'y':
object = Boolean.TRUE;
break;
case 'f':
case 'F':
case 'N':
case 'n':
object = Boolean.FALSE;
break;
default:
throw new IOException("Unknown logical value : '"
+ charBuffer.charAt(fieldOffset) + "'");
}
break;
// (C)character (String)
case 'c':
case 'C':
// oh, this seems like a lot of work to parse strings...but,
// For some reason if zero characters ( (int) char == 0 ) are
// allowed
// in these strings, they do not compare correctly later on down
// the
// line....
int start = fieldOffset;
int end = fieldOffset + fieldLen - 1;
// trim off whitespace and 'zero' chars
while (start < c =" charBuffer.get(start);" c ="="> start) {
char c = charBuffer.get(end);
if (c == 0 || Character.isWhitespace(c)) {
end--;
} else
break;
}
// set up the new indexes for start and end
charBuffer.position(start).limit(end + 1);
String s = charBuffer.toString();
// this resets the limit...
charBuffer.clear();
object = s;
break;
// (D)date (Date)
case 'd':
case 'D':
try {
String tempString = charBuffer.subSequence(fieldOffset,
fieldOffset + 4).toString();
int tempYear = Integer.parseInt(tempString);
tempString = charBuffer.subSequence(fieldOffset + 4,
fieldOffset + 6).toString();
int tempMonth = Integer.parseInt(tempString) - 1;
tempString = charBuffer.subSequence(fieldOffset + 6,
fieldOffset + 8).toString();
int tempDay = Integer.parseInt(tempString);
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, tempYear);
cal.set(Calendar.MONTH, tempMonth);
cal.set(Calendar.DAY_OF_MONTH, tempDay);
object = cal.getTime();
} catch (NumberFormatException nfe) {
// todo: use progresslistener, this isn't a grave error.
}
break;
// (F)floating (Double)
case 'n':
case 'N':
try {
if (header.getFieldDecimalCount(fieldNum) == 0) {
object = new Integer(numberParser.parseInt(charBuffer,
fieldOffset, fieldOffset + fieldLen - 1));
break;
}
// else will fall through to the floating point number
} catch (NumberFormatException e) {
// todo: use progresslistener, this isn't a grave error.
// don't do this!!! the Double parse will be attemted as we
// fall
// through, so no need to create a new Object. -IanS
// object = new Integer(0);
// Lets try parsing a long instead...
try {
object = new Long(numberParser.parseLong(charBuffer,
fieldOffset, fieldOffset + fieldLen - 1));
break;
} catch (NumberFormatException e2) {
}
}
case 'f':
case 'F': // floating point number
try {
object = new Double(numberParser.parseDouble(charBuffer,
fieldOffset, fieldOffset + fieldLen - 1));
} catch (NumberFormatException e) {
// todo: use progresslistener, this isn't a grave error,
// though it
// does indicate something is wrong
// okay, now whatever we got was truly undigestable. Lets go
// with
// a zero Double.
object = new Double(0.0);
}
break;
default:
throw new IOException("Invalid field type : " + type);
}
}
return object;
}
public static void main(String[] args) throws Exception {
FileChannel channel = new FileInputStream(args[0]).getChannel();
DbaseFileReader reader = new DbaseFileReader(channel, false);
System.out.println(reader.getHeader());
int r = 0;
while (reader.hasNext()) {
System.out.println(++r + ","
+ java.util.Arrays.asList(reader.readEntry()));
}
reader.close();
}
}

No comments: