java - 从文件中读取多个对象,就像它们在数组中一样
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27409718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java - Reading multiple objects from a file, as they were in an array
提问by user3435407
I would like to ask the community what do you think about the following situation. The task is to write objects to a file. Which could be made by writing a list of objects to the file that I can read later so I have my objects again. Here, I would write practically ONLY ONE object to the file, namely the list (that may contain more objects).
我想请问社区,您对以下情况有何看法。任务是将对象写入文件。这可以通过将对象列表写入文件来实现,稍后我可以读取该文件,以便我再次拥有我的对象。在这里,我实际上只会将一个对象写入文件,即列表(可能包含更多对象)。
But, the task seams to be to write separate objects to the file, which the method receives from a list. The objects can be whatever. (they must be serializable of course)
但是,任务接缝是将单独的对象写入文件,该方法从列表中接收该文件。对象可以是任何东西。(当然它们必须是可序列化的)
So I did:
所以我做了:
public class TaskStream {
public static void saveObjects(ArrayList<Object> al) {
try {
FileOutputStream fos = new FileOutputStream("outputFile", true);
try {
ObjectOutputStream oos = new ObjectOutputStream(fos);
for (Object o : al){
try {
oos.writeObject(o);
System.out.println("saved");
} catch (NotSerializableException e) {
System.out.println("An object was not serializable, it has not been saved.");
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
This works just fine.
这工作得很好。
But now, I'd like to read them. My first concept about it would be a kind of method, that reads objects until the file has objects, and I can save each of them to a list again (that's the task). So like Pseudo code:
但现在,我想阅读它们。我关于它的第一个概念是一种方法,它读取对象直到文件中有对象,然后我可以将它们中的每一个再次保存到列表中(这就是任务)。所以像伪代码:
for(Object o : fileToRead){ list.add(o) }
How would it be possible? I started to play around with the readObject method of the ObjectInputStream, but it seems to lead to a lot of errors.
怎么可能?我开始尝试使用 ObjectInputStream 的 readObject 方法,但它似乎导致了很多错误。
Do you have any idea? Or what would be the best practice by such a task?
你有什么主意吗?或者这样的任务的最佳实践是什么?
Thanks!
谢谢!
I tried your idea. The exact implementation:
我尝试了你的想法。具体实现:
public static ArrayList<Object> readObjects(){
ArrayList<Object> al = new ArrayList<Object>();
boolean cont = true;
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("outputFile"));
while(cont){
Object obj=null;
try {
obj = ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if(obj != null)
al.add(obj);
else
cont = false;
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return al;
}
To test the program I will write two objects into the file. I read the objects from the file and add them to a list. I iterate through this list and print out the content.
为了测试程序,我将向文件中写入两个对象。我从文件中读取对象并将它们添加到列表中。我遍历这个列表并打印出内容。
If I run the program the following happens (I deleted the outputFile, so the program can recreate it and do everything from scratch).
如果我运行程序,会发生以下情况(我删除了 outputFile,因此程序可以重新创建它并从头开始执行所有操作)。
Result:
结果:
The two objects from the list will be successfully printed. But I receive this:
列表中的两个对象将被成功打印。但我收到这个:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2598)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1318)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
...
...
I don't change anything, and I run the program again. Result:
我没有改变任何东西,我再次运行程序。结果:
The two objects from the list will be successfully printed. But I receive this:
列表中的两个对象将被成功打印。但我收到这个:
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1377)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
From now on, any rerun brings the same result.
从现在开始,任何重新运行都会带来相同的结果。
If I repeat the whole process from the very beginning again (starting by deleting the outputFile) everything happens exactly the same (as expected).
如果我再次从头开始重复整个过程(从删除 outputFile 开始),一切都会发生完全相同(如预期的那样)。
Do you have ideas how to fix it? Thank you very much for the help!
你有解决方法的想法吗?非常感谢你的帮助!
采纳答案by MitchAman
You're going to want to use FileInputStream and ObjectInputStream.
您将要使用 FileInputStream 和 ObjectInputStream。
FileInputStream fis = new FileInputStream("outputFile");
ArrayList<Object> objectsList = new ArrayList<>();
boolean cont = true;
while (cont) {
try (ObjectInputStream input = new ObjectInputStream(fis)) {
Object obj = input.readObject();
if (obj != null) {
objectsList.add(obj);
} else {
cont = false;
}
} catch (Exception e) {
// System.out.println(e.printStackTrace());
}
}
回答by Ankit Chandora
We've to used FileInputStream class method "available" method to check that given stream has data or bytes to read or not if data is not present then this method will return 0;
我们必须使用 FileInputStream 类方法“可用”方法来检查给定的流是否有要读取的数据或字节,如果数据不存在,则此方法将返回 0;
public static ArrayList<Object> getObjects(){
ArrayList<Object> objects = new ArrayList<Object>();
FileInputStream fis = new FileInputStream("outputFile");
ObjectInputStream ois = new ObjectInputStream(fis);
Object obj =null;
boolean isExist = true;
while(isExist){
if(fis.available() != 0){
obj = (A) ois.readObject();
objects.add(obj);
}
else{
isExist =false;
}
}
return objects;
}
回答by pushkars
We can add all the object in a list and then serialize the list. Again we can deserialize the list and we can iterate over the list to get the objects , which we are looking for. It will require the use of below classes. FileOutputStream FileInputStream ObjectInputStream ObjectOutputStream
我们可以将所有对象添加到列表中,然后序列化列表。同样,我们可以反序列化列表,我们可以遍历列表以获取我们正在寻找的对象。它将需要使用以下类。FileOutputStream FileInputStream ObjectInputStream ObjectOutputStream
import java.io.Serializable;
import java.util.List;
import java.util.ArrayList;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
public class MultiObjectSerialization {
static String file = "helloFruits.txt";
static ObjectOutputStream os;
static ObjectInputStream is;
public static void main(String[] args) throws IOException,
ClassNotFoundException {
Apples a = new Apples(1, "apple");
Mango m = new Mango(2, "Mango");
List<Object> fruits = new ArrayList<>();
fruits.add(a);
fruits.add(m);
writeToFile(fruits);
readFile();
}
public static void writeToFile(List<Object> fruits) throws IOException {
os = new ObjectOutputStream(new FileOutputStream(file));
os.writeObject(fruits);
os.close();
}
public static void readFile() throws ClassNotFoundException, IOException {
is = new ObjectInputStream(new FileInputStream(file));
List<Object> input = (List<Object>) is.readObject();
List<Object> checkList = new ArrayList<>();
// this will contain the list of the objects
for (Object l : input) {
checkList.add(l.getClass().getSimpleName());
if (l instanceof Apples) {
Apples app = (Apples) l;
System.out.println(app.id);
System.out.println(app.name);
}
if (l instanceof Mango) {
Mango app = (Mango) l;
System.out.println(app.id);
System.out.println(app.name);
}
}
System.out.println(checkList);
is.close();
}
}
class Apples implements Serializable {
private static final long serialVersionUID = 1L;
int id;
String name;
public Apples(int id, String name) {
this.id = id;
this.name = name;
}
}
class Mango implements Serializable {
private static final long serialVersionUID = 1L;
int id;
String name;
public Mango(int id, String name) {
this.id = id;
this.name = name;
}
}
The Output is ::
1
apple
2
Mango
[Apples, Mango]
回答by KeyboardFlexing
I know the topic is old but i thing i know the solution to this. The reason you get
我知道这个话题很旧,但我知道我知道解决方案。你得到的原因
`'invalid type code: AC'`
is because after you write one object and you try to read it , the ObjectInputStreamis trying to read the info your ObjectOutputStreamwrote. That's how serialization works in general. The problem on your code is that a new ObjectInputStreamis getting created and tries to read back from an old ObjectOutputStreamand it finds out that they don't have the same serial code so you get this error.
是因为在您编写一个对象并尝试读取它之后,ObjectInputStream正在尝试读取您的ObjectOutputStream写入的信息。这就是序列化的一般工作方式。您的代码的问题是正在创建一个新的ObjectInputStream并尝试从旧的ObjectOutputStream读回,但发现它们没有相同的串行代码,因此您会收到此错误。
I found a solution at another topic posted some time ago , check here :stackoverflow solution
我在前段时间发布的另一个主题中找到了解决方案,请在此处查看:stackoverflow 解决方案
What he is doing is that he is overridng the streamWriterwhich "tricks" the ObjectInputStreamto believing that he can read the ObjectOutputStream.
他正在做的是覆盖streamWriter,它“欺骗” ObjectInputStream相信他可以读取ObjectOutputStream。
Hope thats helpfull. Peace out!
希望那有帮助。安息吧!
回答by CodingKick
import java.io.*;
import java.util.*;
class ObjectReadWrite implements Serializable, Comparable <ObjectReadWrite>
{
int no;
String name;
ObjectReadWrite(int i,String s)
{
this.no=i;
this.name=s;
}
public String toString()
{
return "TP Data : "+this.no+":"+this.name;
}
public int compareTo(ObjectReadWrite a1)
{
return this.name.compareTo(a1.name);
}
public static void main(String args[]) throws Exception
{
TreeSet<ObjectReadWrite> aw = new TreeSet<ObjectReadWrite>();
aw.add(new ObjectReadWrite(1,"ABC"));
aw.add(new ObjectReadWrite(2,"DDF"));
aw.add(new ObjectReadWrite(3,"DAF"));
aw.add(new ObjectReadWrite(4,"DCF"));
//Writing Objects From TreeSet
ObjectOutputStream os=new ObjectOutputStream(
new FileOutputStream(
new File("Test.dat")));
os.writeObject(aw);
os.close();
//Reading Objects into TreeSet
TreeSet ar = new TreeSet();
ObjectInputStream is=new ObjectInputStream(
new FileInputStream(
new File("Test.dat")));
ar=(TreeSet)is.readObject();
is.close();
Iterator ir = ar.iterator();
while(ir.hasNext())
{
System.out.println((ObjectReadWrite)ir.next());
}
}
}
回答by acidic_base
The solution is pretty simple. Here you have to handle EOFException
. To do so you have to modify your code as follows -
解决方案非常简单。这里你要处理EOFException
。为此,您必须按如下方式修改代码 -
try {
obj = ois.readObject();
} catch (EOFException e) {
break;
}