如何在Java中将数组写入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(); } } 

使用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(); ... 

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 DatagramSockets和没有流的DatagramSockets非常有用。

我建议简单地使用一些分隔符(例如@@连接字符串中的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); } 

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

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

 outputStream.write(randomNumber); 

在另一边:

 int randomNumber = inputStream.read(); 

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

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

 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(); } } 

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

Android Socket SERVER示例已修改为接收整数数组而不是字符串:

 ... 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(); } } } } ...