【问题标题】:read an Object(customized) from ObjectInputStream从 ObjectInputStream 中读取一个 Object(customized)
【发布时间】:2014-08-19 15:05:04
【问题描述】:

所以,我不知道为什么我的项目的客户端部分给我这种类型的错误

Exception in thread "main" java.lang.ClassNotFoundException: Mining.FrequentPatternMiner at java.net.URLClassLoader$1.run(Unknown Source) at java.net.URLClassLoader$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at java.io.ObjectInputStream.resolveClass(Unknown Source) at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source) at java.io.ObjectInputStream.readClassDesc(Unknown Source) at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source) at java.io.ObjectInputStream.readObject0(Unknown Source) at java.io.ObjectInputStream.readObject(Unknown Source) at JabberClient.main(JabberClient.java:81)

在服务器部分,我转换了FrequentPatternMiner 变量,然后将其提供给ObjectOutputStream

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

FrequentPatternMiner fpMiner=new FrequentPatternMiner(dataTarget, minsup);  
fpMiner.salva("FP_"+nameFile+"_minSup"+minsup+".dat");
System.out.println("Frequent Patterns \n"+fpMiner);

out.flush();
out.writeObject((Object)fpMiner);

在客户端部分,我这样做

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

Object fpMiner=in.readObject();
(((ObjectInput)in).readObject());
System.out.println(fpMiner);

我将如何修复我的代码?你能帮帮我吗?

【问题讨论】:

  • 您正在尝试反序列化它没有的类。我建议您创建一个包含所有对象的 jar,以便在服务器和客户端之间共享,并确保两端的 jar 版本相同。
  • 如何创建这个 jar?
  • 我会使用maven,但您可以使用antjar 命令,或IDE 中的插件。

标签: java client-server objectinputstream objectoutputstream


【解决方案1】:

代码是正确的,但你的前提不是。您已经说过,类“FrequentPatternMiner 对于客户端来说必须是未知的”。在这个前提下,您不能像以前那样序列化类,因为序列化只传输对象的数据,不是它的实现。 您可能想查看 DataTransferObjects(必须在客户端和服务器上都知道)或使用简单的数组来传输对象。

使用简单数组作为“DTO”的示例

服务器:

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());

// The following line assumes that dataTarget and minsup are types 
// that are serializable and known to the client
Object[] objArray = new Object[] { dataTarget, minsup };

out.flush();
out.writeObject(objArray);

客户:

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

Object[] objArray = (Object[])in.readObject();
System.out.println(objArray);

// FrequentPatternMiner must still known to the client, if you need more than 
// the constructor arguments (like methods of the FrequentPatternMiner) Object.
FrequentPatternMiner fpMiner=new FrequentPatternMiner(objArray[0], objArray[1]);

进一步的想法

如果您不希望客户端知道该FrequentPatternMiner 实现/类,您可以尝试“远程处理”或“远程过程调用”(RPC)。这是一门高级主题,有很多库(和平台)提供这种功能。他们基本上是这样做的:

  • 您需要客户端上的类的接口(如interface IPatternMiner { void doMine() }
  • 您连接服务器和客户端(取决于库如何执行此操作)并获取IPatternMiner 的实例
  • 您在接口上调用一个方法,然后在服务器上执行实现(使用从客户端传入的参数)。请注意,文件操作写入服务器上的文件系统

【讨论】:

  • 谢谢你的回答,你能举个例子吗?我必须实现 DataTransferObject 或者我只能在我的项目中导入?我如何使用一个简单的数组?
  • FrequentPatternMiner 应该在客户端执行的方法吗?如果不让客户端知道 jar 中的类,就没有办法(阅读简单的方法)。
【解决方案2】:

您遇到的问题是FrequentPatternMiner 不在您的类路径中。

你可以做的是在 Eclipse 上ctrl+t 并查找FrequentPatternMiner 以了解包含此类的jar 是什么。然后确保您的项目正在引用此类。

如果您使用的是 maven,您可以使用mvm dependency:tree 目标来了解您的项目是否包含此 jar。

【讨论】:

  • 感谢解答,FrequentPatternMiner jar在Server项目中,Client不应该有这个类
  • @user3786467 给出该错误的应用程序肯定没有他的类路径上的 jar。
【解决方案3】:

投射到对象没有任何神奇的属性。一切都可以转换为对象。它不会改变写入对象流的内容是FrequentPatternMiner这一事实,如果该类在接收方不可用,则会导致此异常。

解决方案:部署类。

同样,将 ObjectInputStream 强制转换为 ObjectInput 也没有任何作用。

【讨论】:

  • @downvoter 投射对象是否具有神奇的属性? 部署类?严重地?你的观点?
【解决方案4】:

你需要打样。

System.out.println((FrequentPatternMiner )fpMiner);

否则客户端如何知道正在反序列化的对象的类。请注意,不必为了在sysout 中使用而进行类型转换。它将使用 Objects toString() 方法打印。

虽然你的例外说

Exception in thread "main" java.lang.ClassNotFoundException

您还需要在客户端添加此类。最后检查serialVersionUID 是否与服务器和客户端中的类相同。

【讨论】:

  • 感谢您的回答;)。对于客户端,FrequentPatternMiner 类必须是未知的。我做了两个不同的项目,服务器和客户端一个。在服务器中,我放置了包含所有类的不同包,在客户端中,我只放置了与服务器部分连接的部分
  • System.out.println((FrequentPatternMiner )fpMiner); 完全不需要类型转换。
  • 是的,但没有多大意义,因为对象 toString() 将被调用。
  • OP 不需要类型转换。该对象已经属于该类。您对 Object.toString() 的评论是荒谬的。
  • 这不是 100% 正确的。如果FrequentPatternMiner 实现了toString,那么无论演员如何,都会调用它的toString 实现。所以class Untitled { public static class Blob { public String toString() { return "mine"; } } public static void main(String[] args) { Blob b = new Blob(); System.out.println(b); Object c = b; System.out.println(c); } } 返回相同。
猜你喜欢
  • 1970-01-01
  • 2013-11-09
  • 2016-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-24
  • 1970-01-01
  • 2018-05-20
相关资源
最近更新 更多