通过Java中的套接字发送字符串而不是字节

Posted

技术标签:

【中文标题】通过Java中的套接字发送字符串而不是字节【英文标题】:Send a string instead of byte through socket in Java 【发布时间】:2013-06-30 17:14:22 【问题描述】:

如何使用 getOutputStream 方法发送字符串。它只能像他们提到的那样发送字节。到目前为止,我可以发送一个字节。但不是字符串值。

public void sendToPort() throws IOException 

    Socket socket = null;
    try 
        socket = new Socket("ip address", 4014);
        socket.getOutputStream().write(2); // have to insert the string
     catch (UnknownHostException e) 
        System.err.print(e);
     finally 
        socket.close();
    


提前致谢

【问题讨论】:

要发送一个字符串,您必须首先使用某种编码方案将其转换为字节。 UTF-8 是当今事实上的标准。 【参考方案1】:

使用 PrintWriter 怎么样:

OutputStream outstream = socket .getOutputStream(); 
PrintWriter out = new PrintWriter(outstream);

String toSend = "String to send";

out.print(toSend );

编辑:找到我自己的答案并看到改进被讨论但被遗漏了。这是使用OutputStreamWriter 编写字符串的更好方法:

    // Use encoding of your choice
    Writer out = new BufferedWriter(new OutputStreamWriter(
        new FileOutputStream(fileDir), "UTF8"));

    // append and flush in logical chunks
    out.append(toSend).append("\n");
    out.append("appending more before flushing").append("\n");
    out.flush(); 

【讨论】:

请注意,这里使用的是默认编码而不是显式编码,这很危险 PrintWriter 在 IMO 几乎总是一个坏主意。它吞噬异常的方式很可怕。 @JonSkeet 是的,我不太喜欢我自己提出的解决方案。让我们看看它是否适用于用户。正在考虑更好的解决方案。 @JunedAhsan:好吧,使用OutputStreamWriterwrite 就很简单,允许您指定编码,并避免异常讨厌。 @Ravindu 它会在“大部分时间”工作,具体取决于您通过网络发送的内容类型。所有字符串都必须使用特定的编码转换为字节。每个机器/jvm/os 中的“默认”编码可能不同。因此,您可以放心地假设,如果您不明确设置编码,总有一天会遇到问题。【参考方案2】:

使用OutputStreamWriter类来实现你想要的

public void sendToPort() throws IOException 
    Socket socket = null;
    OutputStreamWriter osw;
    String str = "Hello World";
    try 
        socket = new Socket("ip address", 4014);
        osw =new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
        osw.write(str, 0, str.length());
     catch (IOException e) 
        System.err.print(e);
     catch (UnknownHostException e) 
        System.err.print(e);
     finally 
        socket.close();
    


【讨论】:

由于 *** 可怕的 6 字符编辑量策略,我不得不在这里评论一下,'UTF-8' 应该是“UTF-8”。请记住,单引号用于字符,而双引号用于字符串。【参考方案3】:

两种选择:

将您的OutputStream 包装在OutputStreamWriter 中,这样您就可以发送字符串了 使用String.getBytes(encoding)将字符串转换为字节

请注意,在这两种情况下,您都应该明确指定编码,例如“UTF-8” - 避免它只使用平台默认编码(这几乎总是一个坏主意)。

不过,这只会发送字符数据本身 - 如果您需要发送多个字符串,而另一端需要知道每个字符串的开始和结束位置,您将需要一个更复杂的协议。如果两端都是Java,你可以使用DataInputStreamDataOutputStream;否则您可能想提出自己的协议(假设它尚未修复)。

【讨论】:

嗯,....我对这个套接字及其输入/输出流有点困惑。接收部分呢?我的意思是我们如何区分数据传输是否只是一个字符串/文件? @JonSkeet @gumuruh:这听起来像是一个完全不同的问题。这个问题只是关于发送一个字符串 - 没有什么关于发送文件的。听起来您应该做更多的研究,然后如果您仍然感到困惑,请提出一个新问题。【参考方案4】:

如果你有一个简单的字符串,你可以这样做

socket.getOutputStream().write("your string".getBytes("US-ASCII")); // or UTF-8 or any other applicable encoding...

【讨论】:

【参考方案5】:

你可以像这样使用OutputStreamWriter

OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
out.write("SomeString", 0, "SomeString".length);

您可能要指定字符集,例如"UTF-8" "UTF-16"......

OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream(),
        "UTF-8");
out.write("SomeString", 0, "SomeString".length);

PrintStream:

PrintStream out = new PrintStream(socket.getOutputStream());
out.println("SomeString");

DataOutputStream:

DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeBytes("SomeString");
out.writeChars("SomeString");
out.writeUTF("SomeString");

或者您可以在

中找到更多Writers 和OutputStreams

java.io 包

【讨论】:

【参考方案6】:
public void sendToPort() throws IOException 
    DataOutputStream dataOutputStream = null;
    Socket socket = null;
    try 
        socket = new Socket("ip address", 4014);
        dataOutputStream = new DataOutputStream(socket.getOutputStream());
        dataOutputStream.writeUTF("2"); // have to insert the string
     catch (UnknownHostException e) 
        System.err.print(e);
     finally 
        if(socket != null) 
            socket.close();
        
        if(dataOutputStream != null) 
            dataOutputStream.close();
        
    

注意:您需要从接收端使用 DataInputStream readUTF() 方法。

注意:您必须在“finally”中检查 null;否则你稍后会遇到 NullPointerException。

【讨论】:

注意utf编码不是标准的,是修改后的。【参考方案7】:

我在这篇文章中看到了很多非常有效的解决方案。我最喜欢的是使用 Apache Commons 来做写操作:

IOUtils.write(CharSequence, OutputStream, Charset)

基本上做例如: IOUtils.write("Your String", socket.getOutputStream(), "UTF-8") 并捕获适当的异常。如果您正在尝试构建某种协议,您可以查看 Apache commons-net 库以获取一些提示。

你永远不会出错。 Apache commons-io 中还有许多其他有用的方法和类可以节省您的时间。

【讨论】:

【参考方案8】:

旧帖子,但我可以在大多数帖子中看到相同的缺陷。在关闭套接字之前,刷新流。就像@Josnidhin 的回答一样:

public void sendToPort() throws IOException 
    Socket socket = null;
    OutputStreamWriter osw;
    String str = "Hello World";
    try 
        socket = new Socket("ip address", 4014);
        osw =new OutputStreamWriter(socket.getOutputStream(), 'UTF-8');
        osw.write(str, 0, str.length());
        osw.flush();
     catch (IOException e) 
        System.err.print(e);
     finally 
        socket.close();
    


【讨论】:

以上是关于通过Java中的套接字发送字符串而不是字节的主要内容,如果未能解决你的问题,请参考以下文章

Java - UDP通过套接字发送数据..不是rec。所有数据

Java套接字在写入字节数组后仅获得NUL字符

服务器/客户端未发送所有字节(TCP 套接字)

套字节(socket)

从套接字连接发送和接收字节

如何通过 Dart 中的套接字接收图像