如何使用String
将所有可用字符读取到BufferedReader
?
我有一个Socket
我希望在可用时读取数据,并将其存储在String
中。问题是,我不能使用readLine
,因为我收到的数据并不总是包含换行符或插入符号,readLine
阻塞线程直到它可以读取整行。如何使用read
代替?
thread = new Thread(() ->
{
try {
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
while(true)
{
if (in.ready())
{
String someString = // ? read available data
delegate.didReadData(this, someString);
}
}
} catch (IOException e) {
delegate.didDropSocket(this);
}
});
thread.start();
修改
1.委托不关心字符串有多长,它只需要处理通过套接字到达的任何哈达 - 以及它的全部内容
2.我不需要将数据切割成块 - 我想读取到达的每一个
3.是的,我有一个无限循环,我需要保持连接到套接字并监听数据,直到客户端断开连接 - 当我得到IOException
时。我为套接字使用了一个单独的线程,因为会有更多的套接字要监听。
答案 0 :(得分:2)
您需要始终明确指定您正在使用的编码,在阅读之前无需检查,当然您必须跟踪您已阅读的内容以及另一端是否已关闭连接
省略了异常处理和资源关闭。如有必要,可以增加缓冲区大小。否则这是一个非常惯用的读循环。
out = new PrintWriter(client.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8));
char[] buf = new char[4096];
int size = 0;
while((size = in.read(buf)) != -1) {
String someString = new String(buf, 0, size);
delegate.didReadData(this, someString);
}
答案 1 :(得分:0)
BufferedReader#readLine(0)
treats'\ n','\ r'和“\ r \ n”作为行分隔符。这种行为无法更改,因此,正如您所说,我们需要使用read
的两个重载中的一个。
delegate
需要什么?它关心someString
有多长?您是否需要“填充”从in
读取的数据?您确定String
是否合适?
我怀疑你想要read(char[] cbuf, int off, int len)方法。
假设你不需要一次读取一个字符,那么使用read
的一次性块重载,你将获得更好的性能,而不是使用一次性过载。
另外,你有一个无限循环。即使ready
返回false,您的代码也不会终止,因为您永远不会离开while(true)
循环。
或者这里的意图是让线程不断检查更多数据,而不是结束?我不太熟悉Java标准库来提供详细信息,但我相信有更好的方法可以让线程以100%的负载运行其中一个内核,检查其他数据。简单的黑客就是添加sleep
调用,但我确信有更好的方法,可能涉及Stream
类。