从文件Java null Object读取

时间:2013-05-13 00:38:37

标签: java file static null readfile

我想编写然后从文件中读取一个Object。下面我附上代码示例以向您展示我的想法(它只是示例,我的对象更复杂,但问题是相同的)。

我的问题是:

  1. 如果我不将TestObject字段设置为静态,则testObject.points在readObject方法的启动时变为null。我不明白为什么。有人能给我很好的解释吗?

  2. 我想写一个Object,然后另外两个对象,然后读完它们(多个对象写/读 - 我想为Android创建日志文件)。

  3. 你能帮帮我吗?

    // ... IMPORT

    public class TestObject implements Serializable{
    
        transient public ArrayList<Point[]> points;
    
        public TestObject()
        {
            points = new ArrayList<Point[]>();
            Point[] p1 = new Point[1];
            p1[0] = new Point(1,1);
            Point[] p2 = new Point[2];
            p2[0] = new Point(2,2);
            p2[1] = new Point(2,2);
            points.add(p1);
            points.add(p2);
        }
    
        private void writeObject(ObjectOutputStream stream) throws IOException 
        {
            stream.defaultWriteObject();
            stream.writeInt(points.size());
            Point[] pointsArray = null;
            for (int i = 0; i < points.size(); i++)
            {
                pointsArray = ((Point[])points.get(i));
                stream.writeInt(pointsArray.length);
                for (int j = 0; j < pointsArray.length; j++)
                {
                    stream.writeInt(pointsArray[j].x);
                    stream.writeInt(pointsArray[j].y);
                }
            }
        }
    
        private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException
        {
            stream.defaultReadObject();
            points = new ArrayList<Point[]>();
            int pointsSize = stream.readInt();
            for (int i = 0; i < pointsSize; i++)
            {
                int arraySize = stream.readInt();
                Point[] pointsArray = new Point[arraySize];
                for (int j = 0; j < arraySize; j++)
                {   
                    pointsArray[j] = new Point(stream.readInt(), stream.readInt());
                }
                points.add(pointsArray);
            }
        }
    
        public void writeLog()
        {
            File file = new File ("C:\\!\\", "data.log");
            FileOutputStream fos;
            try {
                fos = new FileOutputStream(file, true);
                //fos = openFileOutput(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data.log", Context.MODE_APPEND);
                ObjectOutputStream os = new ObjectOutputStream(fos);
                os.writeObject(this);
                os.close(); 
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public TestObject readLog()
        {
            TestObject testObject = new TestObject();
            testObject.points = new ArrayList<Point[]>();
            try{
                File file = new File ("C:\\!\\", "data.log");
                FileInputStream fis  = new FileInputStream(file);
                ObjectInputStream reader = new ObjectInputStream(fis);  
                testObject = (TestObject) reader.readObject();
                reader.close();
            } catch (Exception e) {
             //TODO Auto-generated catch block
             e.printStackTrace();
            }
    
            return testObject;
        }
    }
    

    我的主要班级

    // ... IMPORT

    public class Main {
    
        public static void main(String[] args) throws IOException {
    
                TestObject testObject = new TestObject();
                testObject.writeLog();
                testObject.readLog();
    
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    

    同样,这只是一个例子。真正的应用程序适用于Android。

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import android.graphics.Point;
    import android.os.Environment;
    
    public class LogInfo implements Serializable{
    
        /**
         * 
         */
        private static final long serialVersionUID = 2281758309050283667L;
        transient public ArrayList<Point[][]> strokes;
        transient public LinkedList<byte[]> codes;
    
        public LogInfo()
        {
            strokes = new ArrayList<Point[][]>();
            codes = new LinkedList<byte[]>();
        }
    
        private void writeObject(ObjectOutputStream stream) throws IOException 
        {
            stream.defaultWriteObject();
            stream.writeInt(strokes.size());
            Point[][] pointsArray = null;
            for (int i = 0; i < strokes.size(); i++)
            {
                pointsArray = ((Point[][])strokes.get(i));
                stream.writeInt(pointsArray.length);
                for (int j = 0; j < pointsArray.length; j++)
                {
                    stream.writeInt(pointsArray[j].length);
                    for (int k = 0; k < pointsArray[j].length; k++)
                    {
                        stream.writeInt(pointsArray[j][k].x);
                        stream.writeInt(pointsArray[j][k].y);
                        //stream.writeObject(elementData[i]);
                    }
                }
            }
    
            int size = codes.size();
    
            stream.writeInt(size);
            for (int i = 0; i < size; i++)
            {
                stream.write(codes.get(i));
            }
        }
    
        private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException
        {
            strokes = new ArrayList<Point[][]>();
            stream.defaultReadObject();
            int strokesSize = stream.readInt();
            for (int i = 0; i < strokesSize; i++)
            {
                int arrayXSize = stream.readInt();
                Point[][] points = new Point[arrayXSize][];
                for (int j = 0; j < arrayXSize; j++)
                {
                    int arrayYSize = stream.readInt();
                    points[j] = new Point[arrayYSize];
                    for (int k = 0; k < arrayYSize; k++)
                        points[j][k] = new Point(stream.readInt(), stream.readInt());
                }
                strokes.add(points);
            }
    
            int codesSize = stream.readInt();
            codes = new LinkedList<byte[]>();
            for (int i = 0; i < codesSize; i++)
            {
                byte[] buffer = new byte[3];
                stream.read(buffer, 0, 3);
                codes.add(buffer);
            }
        }
    
        public void writeLog()
        {
            File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), "data.log");
            FileOutputStream fos;
            try {
                fos = new FileOutputStream(file, true);
                //fos = openFileOutput(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data.log", Context.MODE_APPEND);
                ObjectOutputStream os = new ObjectOutputStream(fos);
                os.writeObject(this);
                os.close(); 
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public LogInfo readLog()
        {
            try{
                File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), "data.log");
                FileInputStream fis  = new FileInputStream(file);
                ObjectInputStream reader = new ObjectInputStream(fis);  
                reader.readObject();
                reader.close();
            } catch (Exception e) {
             //TODO Auto-generated catch block
             e.printStackTrace();
            }
    
            return this;
        }
    }
    

    我从不同的类调用writeLog和readLog,我有一个对象实例。

    // WRITE TO FILE
    logInfo.writeLog();
    
    // CLEAR LOG VARIABLE (NOT FILE)
    delAllLogInfo();
    
    // READ FROM FILE
    LogInfo newLogInfo = logInfo.readLog();
    

3 个答案:

答案 0 :(得分:1)

  
      
  1. 如果我不将TestObject字段设置为静态,则testObject.points在readObject方法启动时变为null。我不明白为什么。谁能给我很好的解释呢?
  2.   

瞬态字段被反序列化为null。请参阅对象序列化规范。静态字段根本没有反序列化,它们保持当前值。

  
      
  1. 我想写一个Object,然后另外两个对象,然后读完所有(多个对象写/读 - 我想为Android创建日志文件)。
  2.   

如果您始终打开同一个文件,则这不是问题。如果您没有,则需要在第二次及以后的时间以附加模式打开文件,并使用ObjectOutputStream的派生类,该类在第二次及以后的时间内不会写入标题。 / p>

答案 1 :(得分:0)

我看到的关键问题是,你在readLog()方法的开头创建一个新的TestObject对象(这个方法可能应该是静态的)并给它一个ArrayList,但是在mid在方法的主体中,您将这个TestObject实例替换为另一个完全不同的实例,一个通过反序列化来自文件,并且似乎期望新的TestObject将保留已创建并添加到丢弃的TestObject的ArrayList。这不行。解决方案是在 反序列化后创建ArrayList ,以便将其添加到实际从方法返回的TestObject中。

考虑改变这个:

public TestObject readLog()
{
    // the two lines below are at best not necessary and at worst are misleading
    // since the deserialized TestObject will over-write anything done here
    TestObject testObject = new TestObject();  
    testObject.points = new ArrayList<Point[]>(); // again this will be discarded

    try{
        File file = new File ("C:\\!\\", "data.log");
        FileInputStream fis  = new FileInputStream(file);
        ObjectInputStream reader = new ObjectInputStream(fis);  
        testObject = (TestObject) reader.readObject();
        reader.close();
    } catch (Exception e) {
     //TODO Auto-generated catch block
     e.printStackTrace();
    }

    return testObject;

到此:

public static TestObject readLog()
{
    TestObject testObject = null;
    ObjectInputStream reader = null;
    try{
        File file = new File ("C:\\!\\", "data.log");
        FileInputStream fis  = new FileInputStream(file);
        reader = new ObjectInputStream(fis);  
        testObject = (TestObject) reader.readObject();

        testObject.points = new ArrayList<Point[]>();  // **** placement is everything

        // reader.close();
    } catch (Exception e) {
     //TODO Auto-generated catch block
     e.printStackTrace();
    } finally {
      if (reader != null) {
        reader.close();
      }
    }

    return testObject;

或许更好,更清洁,给TestObject一个公共方法,比如说initPoints()让TestObject自己这样做。

public void initPoints() {
   points = new ArrayList<Point[]>();
}

然后在反序列化对象后调用它:

    testObject = (TestObject) reader.readObject();
    testObject.initPoints(); 

无论你做什么,使点数字段保持静态是一个非常非常的坏主意。只是不要考虑它。

附录:如果您的目标实际上是保存Points数据,那么最好的方法是创建自己的Point类并在当前类的包装类中使用它。

答案 2 :(得分:0)

我想我现在明白了。我应该让我的字段不是瞬态的,我的读取Object方法应如下所示:public TestObject readLog()

{
    try{
        File file = new File ("C:\\!\\", "data.log");
        FileInputStream fis  = new FileInputStream(file);
        ObjectInputStream reader = new ObjectInputStream(fis);  
        reader.readObject();
        reader.close();
    } catch (Exception e) {
     //TODO Auto-generated catch block
     e.printStackTrace();
    }

    return this;
}

我说错了吗?这似乎有效