数据传输无法使用ObjectOutputStream.writeObject()

时间:2016-02-24 15:26:54

标签: java android sockets tcp

我创建了一个Android到PC的客户端 - 服务器应用程序,在我的应用程序的其他功能中,我使用ObjectOutputStream.writeObject(AbstractPacket对象)来发送控件和数据我/我的应用程序,它们一切正常,现在当我尝试发送文件(例如:一个小的jpg / png文件),在将文件字节发送到服务器端并重新创建原始jpg文件后,该文件显示其已损坏且未显示,但其大小为与客户端Android应用程序发送的完全相同。 这里有一些代码,

客户端:(文件到bytearray)

  byte [] mybytearray  = new byte [(int)myFile.length()];

FileInputStream fis = new FileInputStream(myFile);

BufferedInputStream bis = new BufferedInputStream(fis);

bis.read(mybytearray, 0, mybytearray.length);

String filename= myFile.getName();

FileTransferPacket packet = new FileTransferPacket(mybytearray,mybytearray.length,filename);
TCPconnection.sendPacket(packet);

FileTransferPacket扩展了AbstractPacket:

public class FileTransferPacket extends AbstractPacket implements Serializable {


byte[] bytes;
long size;
String filename;

public FileTransferPacket(byte[] bytes,long size,String filename) {
super(Protocol.Command.FILE_TRANSFER);
this.bytes = bytes;
this.size = size;

this.filename = filename;
}

public byte[] getBytes() {
return bytes;
}

public long getSize() {return size; }

public String getFilename() {return filename; }
}

这是我如何将数据包对象发送到服务器:

public void sendPacket(AbstractPacket packet) throws IOException {
    connectionOutput.writeObject(packet);
    connectionOutput.flush();
    connectionOutput.reset();

  }

在服务器端,我读取了如下对象:

AbstractPacket packet =(AbstractPacket)connectionInput.readObject();

receiver.handleReceiveData(数据包,连接);

public synchronized void handleReceiveData(AbstractPacket packet, TcpConnection connection) {

String filename=packet.getFilename();
long size= packet.getSize();

byte [] mybytearray  = new byte [(int)size];

byte[] myByteArray=packet.getBytes();

String userHomeFolder = System.getProperty("user.home");

userHomeFolder+="\\Desktop\\"+filename;

try {
FileOutputStream fos = new FileOutputStream(userHomeFolder);

BufferedOutputStream bos = new BufferedOutputStream(fos);

bos.write(mybytearray, 0 , (int)size);

bos.flush();
fos.close();
bos.close();

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

有人可以告诉我这里究竟有什么问题,还请建议如何修复它们。

经过一番搜索后,我确实发现如果我使用普通的OutputStreams只将文件的bytearray发送到服务器,我可以解决它,它可以工作:

outputStream.write(mybytearray,0,mybytearray.length);

但是在我的整个应用程序中我使用了ObjectoutputStream,那么如何在单个套接字上包含这两种类型的流,同样在服务器端如何将传入的数据区分为Object / bytesbuffer。

1 个答案:

答案 0 :(得分:1)

您可以添加控制字节以指示流的类型。 以下是示例代码的工作原理。

这有点棘手。 如果可能,使用不同的端口号会更简单。

import java.io.*;

public class Main {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // File stream.
        FileOutputStream fos = new FileOutputStream("test1.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        // add controll bytes.
        bos.write(0);
        bos.write("file contents".getBytes());
        bos.close();

        // Object stream.
        FileOutputStream fos2 = new FileOutputStream("test2.txt");
        // add controll bytes.
        fos2.write(1);
        ObjectOutputStream oos = new ObjectOutputStream(fos2);
        Exception serializableObj = new RuntimeException("serialize test");

        oos.writeObject(serializableObj);
        oos.close();

        readStream(new FileInputStream("test1.txt"));
        readStream(new FileInputStream("test2.txt"));
    }

    private static void readStream(InputStream in) throws IOException, ClassNotFoundException {
        int controll = in.read();
        if (controll == 0) { // File stream
            BufferedInputStream bis = new BufferedInputStream(in);
            FileOutputStream fos = new FileOutputStream("test3.txt");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            byte[] buff = new byte[1024];
            while (true) {
                int ret = bis.read(buff);
                if (ret < 0) {
                    break;
                }
                bos.write(buff, 0, ret);
            }
            in.close();
            bos.close();

            BufferedReader br = new BufferedReader(new FileReader("test3.txt"));
            String line = br.readLine();
            System.out.println("line: " + line);
            assert (line.equals("file contents"));
            br.close();
        } else if (controll == 1) { // Object stream
            ObjectInputStream ois = new ObjectInputStream(in);
            RuntimeException e = (RuntimeException)ois.readObject();
            assert (e instanceof RuntimeException);
            assert (e.getMessage().equals("serialize test"));
            System.out.println("message: " + e.getMessage());
            ois.close();
        }

    }
}