如何在Java中将数组写入outputStream

时间:2012-12-21 04:09:23

标签: java sockets outputstream

我想通过Socket发送多个随机值。我认为数组是发送它们的最佳方式。但是我不知道如何将数组写入Socket outputStream?

我的java类

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.io.*;
import java.util.Random;

class NodeCommunicator {

public static void main(String[] args) {
try {
    Socket nodejs = new Socket("localhost", 8181);

        Random randomGenerator = new Random();
        for (int idx = 1; idx <= 1000; ++idx){
            Thread.sleep(500);
            int randomInt = randomGenerator.nextInt(35);
            sendMessage(nodejs, randomInt + " ");
            System.out.println(randomInt);
        }

        while(true){
            Thread.sleep(1000);
        }

} catch (Exception e) {
    System.out.println("Connection terminated..Closing Java Client");
    System.out.println("Error :- "+e);
    }

}
        public static void sendMessage(Socket s, String message) throws IOException {
            s.getOutputStream().write(message.getBytes("UTF-8"));
            s.getOutputStream().flush();
        }




 }

7 个答案:

答案 0 :(得分:8)

使用java.io.DataOutputStream / DataInputStream对,他们知道如何读取整数。将信息作为长度+随机数的数据包发送。

发送方

Socket sock = new Socket("localhost", 8181);
DataOutputStream out = new DataOutputStream(sock.getOutputStream());
out.writeInt(len);
for(int i = 0; i < len; i++) {
      out.writeInt(randomGenerator.nextInt(35))
...

接收器

 DataInputStream in = new DataInputStream(sock.getInputStream());
 int len = in.readInt();
 for(int i = 0; i < len; i++) {
      int next = in.readInt();
 ...

答案 1 :(得分:3)

Java数组实际上是Object,而且它们实现了Serializable接口。因此,您可以序列化您的数组,获取字节并通过套接字发送它们。这应该这样做:

public static void sendMessage(Socket s, int[] myMessageArray)
   throws IOException {
  ByteArrayOutputStream bs = new ByteArrayOutputStream();
  ObjectOutputStream os = new ObjectOutputStream(bs);
  os.writeObject(myMessageArray);
  byte[] messageArrayBytes = bs.toByteArray();
  s.getOutputStream().write(messageArrayBytes);
  s.getOutputStream().flush();
}

这真的很简洁,它不仅适用于int[],也适用于任何Serializable对象。

修改 再考虑一下,这更简单:

发送方

public static void sendMessage(Socket s, int[] myMessageArray)
   throws IOException {
  OutputStream os = s.getOutputStream();  
  ObjectOutputStream oos = new ObjectOutputStream(os);  
  oos.writeObject(myMessageArray); 
}

接收器

public static int[] getMessage(Socket s)
   throws IOException {
  InputStream is = s.getInputStream();  
  ObjectInputStream ois = new ObjectInputStream(is);  
  int[] myMessageArray = (int[])ois.readObject(); 
  return myMessageArray;
}

我将离开我的第一个答案(因为它也有效),它对于将对象写入UDP DatagramSocketsDatagramPackets没有任何流非常有用。

答案 2 :(得分:2)

我建议简单地使用一些分隔符连接字符串中的int值,例如: @@,然后立即传输最终的连接字符串。在接收方,只需使用相同的分隔符拆分字符串以获取int[],例如:

    Random randomGenerator = new Random();
    StringBuilder numToSend = new StringBuilder("");
    numToSend.append(randomGenerator.nextInt(35));

    for (int idx = 2; idx <= 1000; ++idx){
        Thread.sleep(500);
        numToSend.append("@@").append(randomGenerator.nextInt(35));
    }
    String numsString = numToSend.toString();
    System.out.println(numsString);
    sendMessage(nodejs, numsString);

在接收方,获取您的字符串并拆分为:

   Socket remotejs = new Socket("remotehost", 8181);
   BufferedReader in = new BufferedReader(
                               new InputStreamReader(remotejs.getInputStream()));
   String receivedNumString = in.readLine();
   String[] numstrings = receivedNumString.split("@@");
   int[] nums = new int[numstrings.length];
   int indx = 0;
   for(String numStr: numstrings){
     nums[indx++] = Integer.parseInt(numStr);
   }

答案 3 :(得分:1)

嗯,流是一个字节流,因此您必须将数据编码为一个字节序列,并在接收端对其进行解码。如何编写数据取决于您希望如何编码它。

0到34之间的数字适合单个字节,这可以很简单:

outputStream.write(randomNumber); 

另一方面:

int randomNumber = inputStream.read();

当然,在每个字节之后刷新流不是很有效(因为它将为每个字节生成一个网络数据包,并且每个网络数据包包含几十个字节的头和路由信息......)。如果性能很重要,你可能也想要使用BufferedOutputStream。

答案 4 :(得分:1)

因此,您可以比较我编写的模板的替代格式,该模板允许您使用您希望的任何格式,或比较替代方案。

abstract class DataSocket implements Closeable {
    private final Socket socket;
    protected final DataOutputStream out;
    protected final DataInputStream in;

    DataSocket(Socket socket) throws IOException {
        this.socket = socket;
        out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    }

    public void writeInts(int[] ints) throws IOException {
        writeInt(ints.length);
        for (int i : ints)
            writeInt(i);
        endOfBlock();
    }

    protected abstract void writeInt(int i) throws IOException;

    protected abstract void endOfBlock() throws IOException;

    public int[] readInts() throws IOException {
        nextBlock();
        int len = readInt();
        int[] ret = new int[len];
        for (int i = 0; i < len; i++)
            ret[i] = readInt();
        return ret;
    }

    protected abstract void nextBlock() throws IOException;

    protected abstract int readInt() throws IOException;

    public void close() throws IOException {
        out.close();
        in.close();
        socket.close();
    }
}

二进制格式,4字节整数

class BinaryDataSocket extends DataSocket {
    BinaryDataSocket(Socket socket) throws IOException {
        super(socket);
    }

    @Override
    protected void writeInt(int i) throws IOException {
        out.writeInt(i);
    }

    @Override
    protected void endOfBlock() throws IOException {
        out.flush();
    }

    @Override
    protected void nextBlock() {
        // nothing
    }

    @Override
    protected int readInt() throws IOException {
        return in.readInt();
    }
}

停止位编码二进制,每7​​位一个字节。

class CompactBinaryDataSocket extends DataSocket {
    CompactBinaryDataSocket(Socket socket) throws IOException {
        super(socket);
    }

    @Override
    protected void writeInt(int i) throws IOException {
        // uses one byte per 7 bit set.
        long l = i & 0xFFFFFFFFL;
        while (l >= 0x80) {
            out.write((int) (l | 0x80));
            l >>>= 7;
        }
        out.write((int) l);
    }

    @Override
    protected void endOfBlock() throws IOException {
        out.flush();
    }

    @Override
    protected void nextBlock() {
        // nothing
    }

    @Override
    protected int readInt() throws IOException {
        long l = 0;
        int b, count = 0;
        while ((b = in.read()) >= 0x80) {
            l |= (b & 0x7f) << 7 * count++;
        }
        if (b < 0) throw new EOFException();
        l |= b << 7 * count;
        return (int) l;
    }
}

最后用新行编码的文本。

class TextDataSocket extends DataSocket {
    TextDataSocket(Socket socket) throws IOException {
        super(socket);
    }

    private boolean outBlock = false;

    @Override
    protected void writeInt(int i) throws IOException {
        if (outBlock) out.write(' ');
        out.write(Integer.toString(i).getBytes());
        outBlock = true;
    }

    @Override
    protected void endOfBlock() throws IOException {
        out.write('\n');
        out.flush();
        outBlock = false;
    }

    private Scanner inLine = null;

    @Override
    protected void nextBlock() throws IOException {
        inLine = new Scanner(in.readLine());
    }

    @Override
    protected int readInt() throws IOException {
        return inLine.nextInt();
    }
}

答案 5 :(得分:0)

如果要向套接字发送多个随机值,请选择一种简单格式并让双方同意(发送方和接收方),例如您只需选择;之类的分隔符并创建包含该分隔符的所有值的字符串,然后发送

答案 6 :(得分:0)

修改

Android Socket SERVER Example以接收整数数组而不是字符串:

...
class CommunicationThread implements Runnable {

    private ObjectInputStream input;

    public CommunicationThread(Socket clientSocket) {

        try {

            this.input = new ObjectInputStream(clientSocket.getInputStream());

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

    public void run() {

        while (!Thread.currentThread().isInterrupted()) {

            try {

                int[] myMessageArray = (int[]) input.readObject();

                String read = null;
                read = String.format("%05X", myMessageArray[0] & 0x0FFFFF);
                int i = 1;
                do {
                    read = read + ", " + String.format("%05X", myMessageArray[i] & 0x0FFFFF);
                    i++;
                } while (i < myMessageArray.length);
                read = read + " (" + myMessageArray.length + " bytes)";

                updateConversationHandler.post(new updateUIThread(read));

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