【问题标题】:Android readObject exception, cannot cast String to ObjectStreamClassAndroid readObject 异常,无法将 String 转换为 ObjectStreamClass
【发布时间】:2013-12-15 00:26:43
【问题描述】:

我正在开发一个远程加载数据的 android 项目,将其保存到数组中(如果数据是新的),将其作为可序列化的数据写入磁盘,然后从磁盘读取数据以加载 ArrayList。

有时 ArrayList 会填充数据,有时不会,程序会崩溃。

我收到一个运行时异常,说明:java.land.ClassCastException: java.lang.String cannot be cast to java.io.ObjectStreamClass。

有时我还会收到 java.io.StreamCorruptedException,有时我会收到 EOFException。

通过异常树,它似乎来自这个调用:

personsArray = (ArrayList<Person>) in.readObject();

现在,有时数据加载正常而没有问题,大多数时候程序崩溃。

以下是将数据保存到磁盘的代码:

public static boolean saveFromRemoteSource(Context c, ArrayList<?> source){
    //Save context
    context = c;

    //Save source to local file
    File file = context.getFileStreamPath(PERSONS_FILE);

    //Status if successful in saving
    boolean savedStatus = false;

    try {
        if(!file.exists()){
            file.createNewFile();
        }else{
            //file already exists so don't do anything
        }
        //now load the data into the file

        FileOutputStream fos = context.openFileOutput(PERSONS_FILE, Context.MODE_PRIVATE);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(source);
        oos.close();
        savedStatus = true; 
    } catch(IOException e){
        e.printStackTrace();
        savedStatus = false; 
    }
    return savedStatus;
}

这是从磁盘读取数据的代码:

    public static boolean loadPersonsArray(Context c){
    context = c;

    boolean loadStatus = false;

    File file = context.getFileStreamPath(PERSONS_FILE);

    try{
            if(!file.exists()){
                file.createNewFile();
            }else {
                //File is already created, do nothing
            }

            BufferedReader br = new BufferedReader(new FileReader(file));     
                if (br.readLine() != null) {
                    FileInputStream fis = context.openFileInput(PERSONS_FILE);
                    ObjectInputStream in = new ObjectInputStream(fis);  
                    personsArray = (ArrayList<Person>) in.readObject();
                    in.close();
                    fis.close();
                    loadStatus = true;
                }
            br.close();
        } catch(IOException e){
            e.printStackTrace();
            Log.d("TAG", "IOException PERSONS_FILE file: " + e);
            loadStatus = false;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            Log.d("TAG", "ClassNotFoundException PERSONS_FILE file classnotfound: " + e);
        }

return loadStatus;
}

这是 Person 类:

    import java.io.Serializable;

     public class Person implements Serializable, Comparable<Person>{
 //Person class

private static final long serialVersionUID = 1L;

private String personID;
private String personName;
private boolean displayPerson;


//default constructor
public Person(){
    super();
}

public Person(String personID,
         String personName,
         boolean displayPerson){

    super();
    this.personID = personID;
    this.personName = personName;
    this.displayPerson = displayPerson; 
}

//Accessor Methods
public String getPersonID(){
    return personID;
}
public String getPersonName(){
    return personName;
}
public boolean getDisplayPerson(){
    return displayPerson;
}

//setter methods

public void setPersonID(String personID){
    this.personID = personID;
}
public void setPersonName(String personName){
    this.personName = personName;
}
public void setDisplayPerson(boolean displayPerson){
    this.displayPerson = displayPerson;
}

@Override
public String toString(){
    return this.getPersonName().replaceAll("[^A-Za-z0-9]", "") + this.getDisplayPerson();
}

public int compareTo(Person otherPerson) {

    if(!(otherPerson instanceof Person)){
        throw new ClassCastException("Not a valid Person object!");
    }

    Person tempPerson = (Person)otherPerson;

    if(this.getPersonName().compareToIgnoreCase(tempPerson.getPersonName()) > 0){
        return 1;
        }else if(this.getPersonName().compareToIgnoreCase(tempPerson.getPersonName()) < 0){
            return -1;
        }else{
            return 0;
        }
     }
}

要写入文件的数据来自哪里

    private void downloadPersons(){     
    HashMap<String, String> params = new HashMap<String, String>();

    Kumulos.call("selectAllPersons", params, new ResponseHandler() {

    @Override
    public void didCompleteWithResult(Object result) {
        ArrayList<Object> personsList = new ArrayList<Object>();

        for(Object o : (ArrayList<?>)result){
            Person person = new Person();                       
            person.setPersonID(replaceNandT((String) ((HashMap<?,?>) o).get("personID")));
            person.setLawName(replaceNandT((String) ((HashMap<?,?>) o).get("personName")));
            person.setDisplayLaw(stringToBool((String)((HashMap<?,?>) o).get("displayPerson")));

            if(person.getDisplayPerson()==true){
                personsList.add(person);
                }
            } 

            //Save personsList to a file
            if(PersonsLoader.saveFromRemoteSource(context, personsList)){
                updateVersionNumber();
                isFinished=true;
                Log.d("TAG", "PersonsLoader.saveFromRemoteSource(context, personsList) success");
                }
        }
    });
}

那么你认为这次电话会议发生了什么?

【问题讨论】:

  • 很可能正在写入文件的任何内容都有错误。这听起来很像一个包含损坏簿记信息的文件。
  • 这是磁盘读取数据的代码。写代码在哪里?还有堆栈跟踪?
  • 我用这个来保存 File file = ontext.getFileStreamPath(PERSONS_FILE);
  • 这还不够。它不保存任何东西。某处还必须有一个打开、一个写入和一个关闭。展示下。将其编辑到您的帖子中。下次当你说“这是将数据保存到磁盘的代码”时,请确保它是真的。
  • 错字,应该说“阅读”。随后我添加了“保存”代码。感谢您的快速回复。

标签: java android bufferedreader fileinputstream objectinputstream


【解决方案1】:

摆脱测试 File.exists() 和 File.createNewFile() 调用的块。

  • 打开文件进行输出将在必要时创建它。
  • 打开文件进行读取时,如果文件不存在,将抛出 FileNotFoundException。创建一个 empty 文件来避免这种情况是没有意义的:它只会导致其他问题。

并摆脱 BufferedReader 和 readLine() 调用。它们没有任何用处。对象输出流中没有行。

【讨论】:

  • 我删除了它们,没有正面/负面结果
  • 因此不需要它们。您必须有一些其他代码写入同一文件。或者 Person 类有什么奇怪的地方,你能发一下吗?
  • 那么代码不会产生那个异常。必须有其他内容写入文件。
  • 我已经添加了上面的代码,显示了数据的来源。
  • 在查看了 Kumulos 调用的 LogCat 之后,对象创建似乎很好。当我想加载数据时,我调用 PersonsLoader.loadOffensesArray(getApplicationContext());它运行你看到的上面的代码。
猜你喜欢
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多