【问题标题】:Generic object Deserialization and Serialization java泛型对象反序列化和序列化java
【发布时间】:2016-05-07 00:03:17
【问题描述】:

您好,我正在学习泛型,我无法将文件中的对象反序列化为泛型列表然后打印。

结果是一个空白屏幕,即使我知道创建了一个 dat 文件

我尝试了多种方法。

我使用带有 ActionListener 的框架..

这是 ActionListener

 private class AddButtonActionListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        // variables    
        String inputfName;
        String inputlName;
        String idInput;
        //String studentID;

        // capture input
        inputfName = sFirstName.getText();
        inputlName = sLastName.getText();
        idInput = sID.getText();

        //hold Student data


        //convert to Int
        //studentID = Integer.parseInt(idInput);

        //Create file
        StudentAddProcess sFile = new StudentAddProcess();
        sFile.writesFile(inputfName, inputlName, idInput );

    }

这些处理输入

公共类 StudentAddProcess 实现 Serializable{

    String inputFirstName ;
    String inputLastName;
     String  inputID;


private Component Frame;

// Create File 
public void  writesFile ( String fName, String  lName, String Id ){

    // create T fields for student

     inputFirstName = fName;
     inputLastName = lName;
     inputID = Id;


try {


    ObjectOutputStream objectInputFile = new ObjectOutputStream(outStream);

    //Linkeked List of Student Objects
    GenericLinkedList<Student> studentList = new GenericLinkedList<>();

    // add Student Object to student 
    studentList.add(new Student(inputID, inputFirstName, inputLastName));

    //Where am i
    JOptionPane.showMessageDialog(Frame, "writing ...");

    //  for loop cycle and write student to fill

        for (int i =0 ;  i < studentList.size();i++) {
            objectInputFile.writeObject(studentList.get(i));
        }

       JOptionPane.showMessageDialog(Frame, "Complete :");
       //close file 
       objectInputFile.close();

现在我们查看添加的对象

    public class StudentViewFile implements Serializable {

    //variables 
    private String studentID; // holds passed user request to view
    private Component Frame;

    public void readFile(String  sID) throws IOException {

    studentID = sID;  // take passed variable
    //int studentID2 =Integer.getInteger(sID);

    try {
        //open read file 


        FileInputStream inStream = new         FileInputStream("StudentObjects.dat");// Stream of Objects

        ObjectInputStream objectInputFile = new ObjectInputStream(inStream);

       GenericLinkedList <Student> readRecord = new  GenericLinkedList<>();

         readRecord.add(new Student(studentID));

        for (int i = 0; i < readRecord.size(); i++) {
            readRecord = (GenericLinkedList) objectInputFile.readObject();

            // Diplay  records 
            System.out.println("File Objects" + readRecord.get(i) + " \n   next positions");

             // was going to try to print my test here  

            System.out.println(readRecord.toString());
        }

        // Read the serialized objects from the file.
        while (true) {

           readRecord = (GenericLinkedList) objectInputFile.readObject();



            // Display  records 
            System.out.println( "File Objects" + readRecord+ " \n next positions");

            //close file 
           objectInputFile.close();
          }

       } catch (EOFException e) {
        System.out.print("\n Exception caught ");

任何想法都会很棒。提前感谢您的时间和知识

【问题讨论】:

  • 这不是问题,但ObjectOutputStream objectInputFile = 是一个奇怪的变量名选择!保证会让试图阅读您的代码的人感到困惑。
  • 为什么要初始化并添加到您立即重新分配的列表中?

标签: java generics linked-list


【解决方案1】:

比较您编写对象的方式与您尝试读取它们的方式。

    for (int i =0 ;  i < studentList.size();i++) {
        objectInputFile.writeObject(studentList.get(i));
    }

这会写入一系列Student 对象。

    readRecord = (GenericLinkedList) objectInputFile.readObject();

这会尝试读取某些内容并将其转换为GenericLinkedList。但它不会是其中之一。它实际上是一个Student,所以你会得到一个异常。

另一个问题是这样的:

    GenericLinkedList <Student> readRecord = new  GenericLinkedList<>();
    readRecord.add(new Student(studentID));
    for (int i = 0; i < readRecord.size(); i++) {
        readRecord = (GenericLinkedList) objectInputFile.readObject();

你真的想循环多少次?这个数字实际上来自哪里?

有很多方法可以解决这个问题;例如:

  1. 将整个列表写入(然后读取)为单个对象
  2. 通过将列表大小 (studentList.size()) 写入 int 来启动流。读取时,先读取列表大小,再读取Student对象的数量。
  3. 使用while (true) 循环读取并捕获/处理EOFException

(我注意到您已尝试执行替代 3 ... 在损坏的代码之后。当然,这不会超过您损坏的代码,因此这不起作用。你在想吗?)

【讨论】:

  • 当最后一个节点不为空时,数字循环来了
  • 好吧,至少这就是我想要的
  • 这不是您的代码实际执行的操作。仔细阅读。它目前正在做的事情实际上是荒谬的。我已经给了你三种正确的方法:使用其中一种。
  • 所以我要捕获读/写文件生成的异常。我想我将不得不尝试从你的帖子中推断出来。我认为你解决的大问题。投射错误的对象...
  • 是的。我不会为你编写代码。这显然是一个“学习练习”,如果您自己理解、编码和测试它,您将学到更多。
【解决方案2】:

嗯,看下面这段代码:

import java.io.*;
import java.util.LinkedList;

public class Main {

    private static class GenericLinkedList<T> extends LinkedList<T> {

    }

    private static class Student implements Serializable {

        final String name;

        public Student(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

    }

    public static void main(String[] args) throws IOException {

        try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            try(ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {

                GenericLinkedList<Student> students = new GenericLinkedList<>();

                seed(students);

                objectOutputStream.writeObject(students);

                try(ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()))) {

                    Object readObject = objectInputStream.readObject();

                    GenericLinkedList<Student> readStudents = (GenericLinkedList<Student>) readObject;

                    for (Student student : readStudents) {
                        System.out.println(student.getName());
                    }

                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    private static void seed(GenericLinkedList<Student> students) {
        for (int i = 0; i < 5; i++) {
            students.add(new Student("test #" + i));
        }
    }

}

它通常适用于通用列表。 Try this code你自己

【讨论】:

  • 感谢您的所有回复,一旦我掌握了知识,我将返回。我会尝试这些并回复
【解决方案3】:

当您将列表序列化为文件时,您通过循环序列化列表中的每个学生对象。

    for (int i =0 ;  i < studentList.size();i++) {
        objectInputFile.writeObject(studentList.get(i));
    }

所以当你反序列化它的时候,你应该一个一个地反序列化学生,而不是整个列表

    GenericLinkedList <Student> readRecord = new  GenericLinkedList<>();
    Student student;
    while (true) {
        student = (Student) objectInputFile.readObject();
        // Display  records 
        System.out.println( "File Objects" + student + " \n next positions");
        readRecord.add(student);
    } catch (EOFException e) {
        System.out.print("\n Exception caught ");
        //close file 
        objectInputFile.close();
    }

【讨论】: