2012-01-11 2 views
2

Мне нужно сериализовать список GeoPoints, а затем прочитать их обратно. Я искал в Интернете и узнал, что могу реализовать свой собственный GeoPoint и реализовать сериализуемый. Он работает, и я могу записать объект в файл .ser, но когда я его прочитал, я получаю invalidclassexception, в котором говорится о подробном сообщении - незаконном доступе к исходному объекту GeoPoint. Я предполагаю, что я не расширяю GeoPoint в классе MyGeoPoint должным образом. может кто-нибудь взглянуть и сказать мне, где я делаю ошибку?Расширение сериализованной геоинформации - невозможно прочитать объект обратно в

import com.google.android.maps.GeoPoint; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 

public class MyGeoPoint extends GeoPoint implements Serializable { 
static final long serialVersionUID = -3010695769693014199L; 


public MyGeoPoint(int latitude, int longitude){ 
    super(latitude, longitude); 
} 
public MyGeoPoint(){ 
    this(0,0); 
} 
private void writeObject(ObjectOutputStream s) throws IOException{ 
    s.defaultWriteObject(); 
} 
private void readObject(ObjectInputStream s) 
     throws java.io.IOException, java.lang.ClassNotFoundException{ 
    s.defaultReadObject(); 
} 
} 

, а затем он привыкает как

File filex = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +"floodData.ser"); 
    MyGeoPoint aPoint = new MyGeoPoint(); 
    MyGeoPoint readPoint = null; 
    //write 
    try{ 
    FileOutputStream f = new FileOutputStream(filex); 
    ObjectOutputStream s = new ObjectOutputStream(f); 
    s.writeObject(aPoint); 
    s.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    //read 
    try { 
    FileInputStream ff = new FileInputStream(filex); 
    ObjectInputStream ss = new ObjectInputStream(ff); 
    readPoint = (MyGeoPoint)ss.readObject(); 
    ss.close(); 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    //end serialisationtest 
+0

и должен также закрыть объект FileOutputStream - е после сериализации части – xyz

+0

@xyz: автоматически закрывающей внешний поток закрывает внутренний поток (см. [здесь] (http://java.sun.com/developer/technicalArticles/Streams/ProgIOStreams/)). Но 'close()' следует вызывать в блоке 'finally'. – Kai

ответ

4

Проблема в том, что GeoPoint не имеет конструктор без аргументов, см JavaDoc в Serializable:

Чтобы разрешить подтипы несериализуемые классы, подлежащие сериализации, подтип может взять на себя ответственность за сохранение и восстановление состояния публики супертипа, защищенный и (если доступен) пакет полей. Подтип может взять на себя эту ответственность, только если класс , который он расширяет, имеет доступный конструктор no-arg для инициализации состояния класса . Ошибка объявить класс Serializable, если это не так. Ошибка будет обнаружена во время выполнения.

И JavaDoc из InvalidClassException

Брошенный, когда сериализация среда определяет один из следующих проблем с классом.

  • Серийная версия класса не соответствует классу дескриптора для чтения из потока
  • Класса содержит неизвестные типы данных
  • Класса не не имеет доступный конструктора без аргументов
0

Чтобы сделать этот ответ более полным, я попытался решить проблему с исправлением бандаи. Попробуйте добавить следующие строки в классе writeObject и readObject ...

private void writeObject(ObjectOutputStream s) throws IOException{ 
    s.writeInt(this.getLatitudeE6()); 
    s.writeInt(this.getLongitudeE6()); 
} 
private void readObject(ObjectInputStream s) 
     throws java.io.IOException, java.lang.ClassNotFoundException{ 
    this(s.readInt(), s.readInt()); 
} 
1

Вам не нужно продлить com.google.android.maps.GeoPoint иметь сериализуемую объект для хранения координат широты/долготы.

И поскольку вы не являетесь владельцем оригинального объекта, вы не должны этого делать, потому что если Google решит изменить исходный GeoPoint и скажем ... добавьте/удалите методы, замените подписи методов и т. Д. ... вы можете получить в беды.

Хуже того, ваш код не будет переносимым, FYI Android на Kindle Fire не имеет доступа к API Карт Google, поэтому ваше приложение, распространяющееся с com.google.android.maps.GeoPoint, не будет работать.

путь заключается в создании Serializable POJO с теми же свойствами точных (и его типов) для хранения вашей широты/долготы координат, что вы будете сериализовать:

package com.yourapp.beans; 

public class YourGeoPoint implements Serializable { 

     private static final long serialVersionUID = -99127398709809L; 

     private int latitudeE6; 
     private int longitudeE6; 

     public YourGeoPoint() { 
      this.setLatitudeE6(0); 
      this.setLongitudeE6(0); 
     } 

     public YourGeoPoint(int latitudeE6, int longitudeE6) { 
      this.setLatitudeE6(latitudeE6); 
      this.setLongitudeE6(longitudeE6); 
     } 

     public int getLatitudeE6() { 
      return latitudeE6; 
     } 

     public void setLatitudeE6(int latitudeE6) { 
      this.latitudeE6 = latitudeE6; 
     } 

     public int getLongitudeE6() { 
      return longitudeE6; 
     } 

     public void setLongitudeE6(int longitudeE6) { 
      this.longitudeE6 = longitudeE6; 
     } 

    } 

Тогда всякий раз, когда вам нужно com.google.android.maps.GeoPoint ... и после того, как десериализацией к yourGeoPoint например, просто сделать:

import com.google.android.maps.GeoPoint; 
import com.yourapp.beans.YourGeoPoint; 
//...  
YouGeoPoint yourGeoPoint = // De-serialization...   
GeoPoint geoPoint = new GeoPoint(yourGeoPoint.getLatitudeE6(), yourGeoPoint.getLongitudeE6()); 

Он работает на 100%, и ваш код будет переносим на устройствах Android, где API Google Maps нет ... если это случай, просто импортируйте любые библиотеки библиотек, которые у вас есть ess (например, ESRI или OpenSignalMaps) и получить один из своих «GeoPoints» или эквивалентный объект с координатами, исходящими от вашего собственного де-сериализованного объекта.

Cheers!

0

уборщика подход не мешая другой код, чтобы изменить свой класс и присваиватель к:

private double lat; 
private double lng; 

public LatLng getLocation() { 
    LatLng latLng = new LatLng(this.lat, this.lng); 

    return latLng; 
} 

public void setLocation(LatLng location) { 

    this.lat = location.latitude; 
    this.lng = location.longitude; 
} 
Смежные вопросы