如何克服"\ n"使用.readlines()方法时 [英] how to overcome "\n" when using .readlines() methode

查看:101
本文介绍了如何克服"\ n"使用.readlines()方法时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用套接字,并且收到来自服务器的响应,该响应是 string .

方法 readline() 不断循环,因为我的响应在每个响应末尾都没有/n/r.所以我的程序被卡在那一行.

我如何接收响应,换句话说,如何告诉readline()方法传输已经结束,而响应末尾没有/n/r? 我不能使用read()方法,因为它返回一个int值.这里的接收代码

// Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);


// lecture de message

String message = br.readLine();

这是iam要求得到的响应"162143045875965485214752310109013112500019900008080807812345612345678912500007412589600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

解决方案

TCP是一种流协议,这意味着只要套接字已连接,字节就无休止地来自套接字.因此,数据不会分为单独的消息.因此,从TCP套接字读取与从二进制文件读取非常相似-您不能只逐行读取,因为它们都是带有开始和结束位置的数据块.

如果输入在消息之间不包含定界符,例如\n(或某些其他字符或字节序列),则必须采用其他方法确定要读取多少个字节.取决于协议,有几种解决方法.例如,在HTTP中,响应通常具有Content-Length标头,以便读者知道此响应何时结束以及下一个响应开始.

如果要实现自己的协议,一种简单的方法是为每个消息添加int前缀,指定其包含的字节数.在这种情况下,读取器所需要做的就是读取int,从套接字读取适当数量的字节,解析消息,然后读取下一个int ...

另一种方法是使用固定大小的消息,并且每次仅读取固定数量的字节.第三种方法是使用分隔符,例如\n或其他未出现在协议有效负载中的字节序列.

如果知道要读取的字节数,请首先创建一个缓冲区以将消息写入其中.假设我们要精确读取500个字节.分配消息缓冲区:

byte messageBuffer[] = new byte[500];

现在,我们需要从套接字读取直到满足以下两个条件之一:

  • 消息缓冲区中有500个字节
  • 或者插座已关闭

方便地,每次在套接字的InputStream上调用read时,我们都会获取已读取的字节数,如果流已结束,则返回-1.因此,我们可以读入消息缓冲区,直到用500个字节填充它,或者从read()调用中得到-1.

我们最终遇到这样的循环:

int bytesToRead = 500;
InputStream in = socket.getInputStream();
byte messageBuffer[] = new byte[bytesToRead];
for (int readOffset = 0, readBytes = 0; (readBytes = in.read(messageBuffer, readOffset, messageBuffer.length - readOffset)) != -1
        && readOffset < bytesToRead;) {
    readOffset += readBytes;
}

或者,如果您愿意,也可以这样:

int readBytes = 0;
int readOffset = 0;
while (true) {
    readBytes = in.read(messageBuffer, readOffset, messageBuffer.length - readOffset);
    if (readBytes == -1) {
        break;
    }
    readOffset += readBytes;
}

请注意,我尚未测试此代码.

一旦您已将足够的字节读入缓冲区,如果要使用它们制成String,则如果要指定非默认字符集,请使用new String(messageBuffer)或类似new String(messageBuffer, Charset.forName("UTF-8"))的名称. /p>

I am using a socket and I am receiving a response from a server which is a string.

The method readline() keeps looping because my response doesn't have a /n or /r at the end of every response. So my program gets stuck at that line.

How do I receive the response, in other words how to tell the readline() method that the transmission is over without having /n or /r at the end of the response? i can not use read() methode because it return an int. herese the reception code

// Get the return message from the server
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);


// lecture de message

String message = br.readLine();

and this is the response that iam suposed to get "162143045875965485214752310109013112500019900008080807812345612345678912500007412589600000000000000000000000000000000000000000000000000000000000000000000000000000000"

解决方案

TCP is a stream protocol, which means that bytes are coming from the socket endlessly as long as the socket is connected. The data is therefore not divided into individual messages. Thus, reading from a TCP socket is very similar to reading from a binary file - you can't just read "line by line" since it's all just a blob of data with a start and and end.

If the input doesn't contain delimiters such as \n (or some other character or sequence of bytes) between messages, then there has to be some other way of determining how many bytes to read. There are several approaches to this, depending on the protocol. For instance, in HTTP, responses typically have Content-Length header so that the reader knows when this response ends and the next one begins.

If you're implementing your own protocol, a simple approach is to prefix each message with an int specifying the number of bytes it contains. In that case, all the reader has to do is to read the int, read the appropriate number of bytes from the socket, parse the message, then read the next int...

Another approach is to use fixed-sized messages, and to simply read a fixed number of bytes every time. A third approach is to use a delimiter, like \n or some other sequence of bytes that does not appear in the payload of your protocol.

If you know the number of bytes you want to read, first create a buffer to write the message to. Say we want to read exactly 500 bytes. Allocate the message buffer:

byte messageBuffer[] = new byte[500];

Now we need to read from the socket until one of two conditions are met:

  • There are 500 bytes in the message buffer
  • Or the socket is closed

Conveniently, each time we call read on the InputStream of the socket, we get the number of bytes we've read, or -1 if the stream has ended. Hence, we can read into our message buffer until we either fill it up with 500 bytes, or we get -1 from the read() call.

We end up with a loop like this:

int bytesToRead = 500;
InputStream in = socket.getInputStream();
byte messageBuffer[] = new byte[bytesToRead];
for (int readOffset = 0, readBytes = 0; (readBytes = in.read(messageBuffer, readOffset, messageBuffer.length - readOffset)) != -1
        && readOffset < bytesToRead;) {
    readOffset += readBytes;
}

Or, if you prefer, like this:

int readBytes = 0;
int readOffset = 0;
while (true) {
    readBytes = in.read(messageBuffer, readOffset, messageBuffer.length - readOffset);
    if (readBytes == -1) {
        break;
    }
    readOffset += readBytes;
}

Note I haven't tested this code.

Once you've read enough bytes into the buffer, if you want to make a String out of them, just use new String(messageBuffer) or something like new String(messageBuffer, Charset.forName("UTF-8")) if you want to specify a non-default charset.

这篇关于如何克服"\ n"使用.readlines()方法时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆