小弟使用socket向客户端发一个自定义对象,强制转换时出现java.io.StreamCorruptedException: Wrong format异常,不知如何解决
异常信息如下10-23 02:20:58.687: W/System.err(1276): java.io.StreamCorruptedException: Wrong format: ac
10-23 02:20:58.689: W/System.err(1276):  at java.io.ObjectInputStream.corruptStream(ObjectInputStream.java:701)
10-23 02:20:58.689: W/System.err(1276):  at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:814)
10-23 02:20:58.689: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
10-23 02:20:58.689: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
10-23 02:20:58.689: W/System.err(1276):  at com.wsst.utils.SocketUtil$1.run(SocketUtil.java:77)
10-23 02:20:58.689: W/System.err(1276):  at java.lang.Thread.run(Thread.java:856)
10-23 02:20:58.689: W/System.err(1276): java.io.StreamCorruptedException: Wrong format: ed
10-23 02:20:58.699: W/System.err(1276):  at java.io.ObjectInputStream.corruptStream(ObjectInputStream.java:701)
10-23 02:20:58.699: W/System.err(1276):  at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:814)
10-23 02:20:58.699: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
10-23 02:20:58.699: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
10-23 02:20:58.709: W/System.err(1276):  at com.wsst.utils.SocketUtil$1.run(SocketUtil.java:77)
10-23 02:20:58.709: W/System.err(1276):  at java.lang.Thread.run(Thread.java:856)
10-23 02:20:58.709: W/System.err(1276): java.io.StreamCorruptedException: Wrong format: 0
10-23 02:20:58.709: W/System.err(1276):  at java.io.ObjectInputStream.corruptStream(ObjectInputStream.java:701)
10-23 02:20:58.709: W/System.err(1276):  at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:814)
10-23 02:20:58.709: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
10-23 02:20:58.709: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
10-23 02:20:58.709: W/System.err(1276):  at com.wsst.utils.SocketUtil$1.run(SocketUtil.java:77)
10-23 02:20:58.709: W/System.err(1276):  at java.lang.Thread.run(Thread.java:856)
10-23 02:20:58.719: W/System.err(1276): java.io.StreamCorruptedException: Wrong format: 5
10-23 02:20:58.719: W/System.err(1276):  at java.io.ObjectInputStream.corruptStream(ObjectInputStream.java:701)
10-23 02:20:58.719: W/System.err(1276):  at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:814)
10-23 02:20:58.719: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
10-23 02:20:58.719: W/System.err(1276):  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
10-23 02:20:58.719: W/System.err(1276):  at com.wsst.utils.SocketUtil$1.run(SocketUtil.java:77)
10-23 02:20:58.729: W/System.err(1276):  at java.lang.Thread.run(Thread.java:856)

解决方案 »

  1.   

    反序列化问题。
    http://hi.baidu.com/chinalwb/item/bffa8745c7cd522011ee1e6b
      

  2.   

    所有的Object传输都是要序列化的,不管集合也好,字符串也好,都是序列化的对象,就会出错。还是贴下你的代码吧。
      

  3.   

    我通过socket传送的所有对象的类,都实现了Serializable,代码有些长,我贴一下
    Command类
    package com.wsst.common;
    import java.io.Serializable;public class Command implements Serializable{ private static final long serialVersionUID = 1L; //序列化对象
    public static final String CLIENT_INDEX ="ClientIndex"; //指令值(用户唯一标识)command
    public static final String GET_PLAYER_COUNT ="GetPlayerCount"; //获取玩家总数command
    public static final String GET_ALL_ROOM ="GetAllRoom"; //获取房间信息command
    public static final String CREATEROOM ="CreateNewRoom"; //创建新房间command
    public static final String GETINROOM ="GetInRoom"; //加入指定房间command
    public static final String STARTGAME ="StartGame"; //下发比赛题目command
    public static final String USERTABLE ="UserTable"; //本地用户信息command
    public static final String REGISTERVALID ="RegisterValid"; //用户提交注册信息command
    public static final String TEST = "test";

    public String LevelInfo; //题别信息
    public String RoomList; //room列表
    private String CommendHead;  //command头
    private String CommendValue;  //command值
    private int ClientIdx; //指令值(用户唯一标识)
    private Player player; //玩家对象
    private String groupArr; //存放指定级别的题号字符串
    private String userInfo; //存放用户注册信息的字符串
    private Room room;

    public Room getRoom() {
    return room;
    }
    public void setRoom(Room room) {
    this.room = room;
    }
    public String getLevelInfo() {
    return LevelInfo;
    }
    public void setLevelInfo(String levelInfo) {
    LevelInfo = levelInfo;
    }
    public String getUserInfo() {
    return userInfo;
    }
    public void setUserInfo(String userInfo) {
    this.userInfo = userInfo;
    }
    private int RoomID;

    public int getRoomID() {
    return RoomID;
    }
    public void setRoomID(int roomID) {
    RoomID = roomID;
    }

    public String getGroupArr() {
    return groupArr;
    }
    public void setGroupArr(String groupArr) {
    this.groupArr = groupArr;
    }
    public  Command(){
         super();
    }
    public  Command(String head,String value,int index){
    super();
    CommendHead = head;
    CommendValue = value;
    ClientIdx = index;
    }

    public String getRoomList() {
    return RoomList;
    }
    public void setRoomList(String roomList) {
    RoomList = roomList;
    }
    public String getCommendHead() {
    return CommendHead;
    }
    public void setCommendHead(String commendHead) {
    CommendHead = commendHead;
    }
    public String getCommendValue() {
    return CommendValue;
    }
    public void setCommendValue(String commendValue) {
    CommendValue = commendValue;
    }
    public int getClientIdx() {
    return ClientIdx;
    }
    public void setClientIdx(int clientIdx) {
    ClientIdx = clientIdx;
    }
    public Player getPlayer() {
    return player;
    }
    public void setPlayer(Player player) {
    this.player = player;
    }
    }
    Player类
    package com.wsst.common;import java.io.Serializable;public class Player implements Serializable {

    private static final long serialVersionUID = 1L;   //序列化对象
    private String name; //玩家账号昵称
    private String ipAdress; //玩家IP
    private int clientId; //玩家指令值
    private int roomID; //玩家所在的房间号
    private String totalScores;         //玩家游戏得分
    private String selectedItem;          //玩家某项题目所选答案

    public Player(int clientIndex) {
    this.clientId = clientIndex;
    } public String getIPAdress() {
    return ipAdress;
    } public void setIPAdress(String iPAdress) {
    this.ipAdress = iPAdress;
    } public int getClientIdx() {
    return clientId;
    }
    public void setClientIdx(int clientIdx) {
    this.clientId = clientIdx;
    } public int getRoomID() {
    return roomID;
    } public void setRoomID(int roomID) {
    this.roomID = roomID;
    }

    public String getName() {
    return name;
    } public void setName(String Name) {
    this.name = Name;
    }

    public String getTotalScores() {
    return totalScores;
    } public void setTotalScores(String TotalScores) {
    this.totalScores = TotalScores;
    }

    public String getSelectedItem() {
    return selectedItem;
    } public void setSelectedItem(String SelectedItem) {
    this.selectedItem = SelectedItem;
    }
    }Socket传送部分代码
    // 接收
    public void run() {
     try {
       while ((mCommend = (Command) mInputStream.readObject()) != null{}
    }catch。。
    传送跟接收的代码一样一样
      

  4.   

    mInputStream 是什么类?ObjectInputStream 吗?它怎么初始化的
      

  5.   

    代码已经贴出来了,麻烦看一下private Socket mSocket;
    private ObjectInputStream mInputStream;
    private ObjectOutputStream mOutputStream;
    private Command mCommend = null;
    private int romNum = 10;
    private boolean flg = false; // false 验证未通过;true 验证通过
    private String levelStr = null; // 存放服务器端的题库名称及大小的字符串
    private Map<String, String> userinfo_map = null; public ThreadServer(Socket socket) {
    try {
    this.mSocket = socket;
    // 创建输入/输出流
    mInputStream = new ObjectInputStream(socket.getInputStream());
    mOutputStream = new ObjectOutputStream(socket.getOutputStream());这个问题困扰了很久,特别希望解决掉
      

  6.   

    private Socket mSocket;
    private ObjectInputStream mInputStream;
    private ObjectOutputStream mOutputStream;
    private Command mCommend = null;
    private int romNum = 10;
    private boolean flg = false; // false 验证未通过;true 验证通过
    private String levelStr = null; // 存放服务器端的题库名称及大小的字符串
    private Map<String, String> userinfo_map = null;public ThreadServer(Socket socket) {
    try {
    this.mSocket = socket;
    // 创建输入/输出流
    mInputStream = new ObjectInputStream(socket.getInputStream());
    mOutputStream = new ObjectOutputStream(socket.getOutputStream());这个问题困扰了很久,特别希望解决掉
      

  7.   

    那就是直接的 InputStream 了。
    InputStream.read() 并不会读取 InputStream 里的所有东西,它只读取有效字节。
    因为你是实时传送,所以你读到的东西可能只是发送的一部分。
    造成错误。
      

  8.   


    那我应该如何解决呢?
    不使用InputStream.read()方法的话有什么别的替代方法吗?
    还是说不使用InputStream呢?
      

  9.   


    我还是有些不理解您说的话,我使用InputStream.read()方法,那我怎么去了解它是如何读的呢?
      

  10.   

    你先想着怎么解决问题。给你个例子吧
    int len = buildShort(bytes2[0], bytes2[1]);
    byte[] recvData = new byte[len];
    int totalCount = 0;
    int readCount = 0;
    while (totalCount < len ) {
    readCount = inputStream.read(recvData, totalCount, len - totalCount);
    if (readCount == -1)
    throw new BaseException(GlobalConstant.ERROR_CODE_40032);
    totalCount = readCount + totalCount;
    }
      

  11.   


    我理解上面例子的含义是:一直读取输入流【while (totalCount < len )】,直到不满足条件。我想问一下,(Command) mInputStream.readObject()这个是不是也应该有方法不断读取里面的对象,我想找到其中某个匹配的Command?我试了一下,while (mInputStream.readObject().equals(true))这样问题好像更多了,异常还是会出现,希望帮忙指导一下。
      

  12.   

    Socket传送部分代码
    // 接收
    public void run() {
     try {
       while ((mCommend = (Command) mInputStream.readObject()) != null{}
    }catch。。
    传送跟接收的代码一样一样如果传送跟接收代码一样,而且传送用的是ObjectOutputStream的话,那么ObjectOutputStream 不能直接追加,因为每次追加都会添加进一个Header。
    所以反序列化的时候,才会出现这个异常。其中一个解决方案是 重写下ObjectOutputStream的writeStreamHeader()函数。
      

  13.   

    这样说来,问题出在ObjectOutputStream的机制上,如果换一个,比如DataOutputStream,不知还会不会出现这种情况,我先试一试
      

  14.   

    /** 
         * 对象转数组 
         * @param obj 
         * @return 
         */  
        public byte[] toByteArray (Object obj) {     
            byte[] bytes = null;     
            ByteArrayOutputStream bos = new ByteArrayOutputStream();     
            try {       
                ObjectOutputStream oos = new ObjectOutputStream(bos);        
                oos.writeObject(obj);       
                oos.flush();        
                bytes = bos.toByteArray ();     
                oos.close();        
                bos.close();       
            } catch (IOException ex) {       
                ex.printStackTrace();  
            }     
            return bytes;   
        }  
          
        /** 
         * 数组转对象 
         * @param bytes 
         * @return 
         */  
        public Object toObject (byte[] bytes) {     
            Object obj = null;     
            try {       
                ByteArrayInputStream bis = new ByteArrayInputStream (bytes);       
                ObjectInputStream ois = new ObjectInputStream (bis);       
                obj = ois.readObject();     
                ois.close();  
                bis.close();  
            } catch (IOException ex) {       
                ex.printStackTrace();  
            } catch (ClassNotFoundException ex) {       
                ex.printStackTrace();  
            }     
            return obj;   
        }  这两个方法有什么问题吗,为什么返回的结果是NULL呢