91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

geoserver rest 導入shape文件錯誤

發布時間:2020-07-03 12:07:55 來源:網絡 閱讀:613 作者:rumeng_you 欄目:編程語言

使用rest接口導入shp文件時出錯,
java.io.ioexception: current fid index is null, next must be called before write(),
網上找了一下,找到了一篇文章,地址http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E7%9A%84/14090.shtml

自己又仔細研究了一下出錯的地方的源碼,先貼一下在講原因

org.geotools.data.shapefile.dbf.DbaseFileWriter

public String getFieldString(int size, String s) {
            try {
                buffer.replace(0, size, emptyString);
                buffer.setLength(size);
                // international characters must be accounted for so size != length.
                int maxSize = size;
                if (s != null) {
                    buffer.replace(0, size, s);
                    int currentBytes =
                            s.substring(0, Math.min(size, s.length()))
                                    .getBytes(charset.name())
                                    .length;
                    if (currentBytes > size) {
                        char[] c = new char[1];
                        for (int index = size - 1; currentBytes > size; index--) {
                            c[0] = buffer.charAt(index);
                            String string = new String(c);
                            buffer.deleteCharAt(index);
                            currentBytes -= string.getBytes().length;
                            maxSize--;
                        }
                    } else {
                        if (s.length() < size) {
                            maxSize = size - (currentBytes - s.length());
                            for (int i = s.length(); i < size; i++) {
                                buffer.append(' ');
                            }
                        }
                    }
                }

                buffer.setLength(maxSize);

                return buffer.toString();
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("This error should never occurr", e);
            }
        }

以下是個人分析,可能有不對的地方,見諒:
主要原因是有中文字符引起的
dbf文件中是按字節存儲的,而一個漢字,GBK是2個字節,UTF-8是三個字節,StringBuffer 里的charAt是按字符算的,geoserver rest上傳文件的過程,不是直接按字節保存的,而是讀取shape的全部內容,包括dbf,然后再寫入到一個新的shape文件中。

如果遇到String類型的屬性,會調用 getFieldString(int size,String s)方法,截取掉多余的字節,下面舉一個真實的例子,size 20,s是"福建省福州市羅源縣",UTF-8編碼轉換為字節是27,27大于字段長度20,需要截取出前20個字符來。
但是方法內部是用的從末尾刪除的方法,具體看下面圖片。
geoserver rest 導入shape文件錯誤

大家可以仔細研究一下代碼,總結一下:
如果是UTF-8編碼,則字段長度必須設計為value長度的3倍
如果是GBK邊框,則字段長度必須設計為value長度的2倍
,否則的話如果存儲的中文字段getBytes之后超過字段的length,則會報錯。

java.lang.StringIndexOutOfBoundsException: String index out of range: 19

不知道修改下代碼,強行把多余的字符寫入到dbf文件中是否會報錯,因為這個本來就是存儲在dbf文件中的,但是是從其他軟件中導出的,不是用geotools生成的。

如果哪位大神知道,請留言解釋一下。

自己想了個解決方案
在調用rest接口之前,把dbf文件重寫一遍,定義字段的時候,字段長度定義為原來的3倍,這樣geoserver在遇見中文的時候就不會報錯了。

貼一下簡單的代碼

<dependency>
        <groupId>com.github.albfernandez</groupId>
        <artifactId>javadbf</artifactId>
        <version>1.9.2</version>
 </dependency>
public static void changeStringLength(String dbfName, String dbfCharest, String ndbfName,
      String newCharset)
      throws Exception {

    try (DBFReader reader = new DBFReader(
        new FileInputStream(dbfName), Charset.forName(dbfCharest));
        DBFWriter writer = new DBFWriter(new FileOutputStream(ndbfName),
            Charset.forName(newCharset))
    ) {

      int numberOfFields = reader.getFieldCount();

      //改變字符串字段的長度
      List<DBFField> fields = Lists.newArrayList();

      for (int i = 0; i < numberOfFields; i++) {
        DBFField field = reader.getField(i);
        //處理字段字符串字段  乘以3,為了適應UTF8是3個字節的問題
        if (field.getType().equals(DBFDataType.CHARACTER) || field.getType()
            .equals(DBFDataType.VARCHAR)) {
          int maxLength = field.getLength() * 3;
          if (maxLength > field.getType().getMaxSize()) {
            maxLength = field.getType().getMaxSize();
          }
          field.setLength(maxLength);
        }
        fields.add(field);
      }

      //設置新文件的頭
      writer.setFields(fields.toArray(new DBFField[fields.size()]));

      Object[] rowObjects;

      while ((rowObjects = reader.nextRecord()) != null) {
        writer.addRecord(rowObjects);
      }

    }

  }

通過以上方案暫時解決了中文字符過長的問題,但是不知道會不會觸發其他的bug。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金乡县| 昌邑市| 贡觉县| 富民县| 微山县| 车险| 大洼县| 蒙自县| 禄劝| 普安县| 洪泽县| 重庆市| 山西省| 孝感市| 常德市| 福海县| 巴里| 微山县| 黄平县| 文化| 桃园市| 彭阳县| 昌吉市| 临汾市| 枝江市| 黔西县| 井冈山市| 海兴县| 黄骅市| 城市| 保山市| 抚松县| 漾濞| 南阳市| 林西县| 福海县| 泰兴市| 教育| 黔西县| 应城市| 法库县|