BufferedReader - 读取所有字符(不是行)

时间:2018-01-06 12:49:13

标签: java bufferedreader

如何使用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时。我为套接字使用了一个单独的线程,因为会有更多的套接字要监听。

2 个答案:

答案 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类。