JAVA流read阻塞或readLine阻塞解决方法

  • 前言:
  • 原因:
  • 方法一:
  • 方法二:


前言:

在做 Android 端(Java) 和 PC 端(C++) 通信时;C++ 端发送“D75489DBAC19D962F8605B65F5414BC5$幸运.txt$199” 格式消息时,使用 Java 流读取阻塞;

原因:

C++ 语言中,以 \0 作为发送完成的标值,而 Java 中流的 read() 或者 readLine() 都是以 \r 或者 \n 为结束,所以读取发送过来的消息时,总是发生阻塞,这也读取流,这两个方法的坑!!!

方法一:

  1. (参考)舍弃部分信息以跳出 read() 阻塞:
  2. 代码如下,以标值符号 $ 去截取,不过,由于无法跳出读取阻塞的问题,我舍弃了文件大小;以下是之前源码;仅作参考;
StringBuffer fileRequestBff = new StringBuffer("");
int nameSize;
boolean isBreak = false;
while ((nameSize = br.read()) > 0) {
    if ('$' == (char) (nameSize)) {//这里对$的个数进行判断。到达第二个时,不接收 size 直接跳出;
        num++;
        isBreak = (num == 2) ? true : false;
        if (isBreak) break;
    }
    char temp = (char) nameSize;
    fileRequestBff.append(temp);
    //Log.i(TAG, "ReceiveFile name size  =  " + nameSize + " name = " + temp + "  " );
}
Log.i(TAG, "ReceiveFile    name =  " + fileRequestBff);
//接收到的发送请求
String fileRequestStr = fileRequestBff.toString();
//1. 接收到完成的发送请求;取出MD5、文件名、文件大小;
String MD5 = fileRequestBff.substring(0, fileRequestStr.indexOf("$"));
//除去MD5  和 $ 后的内容
fileRequestStr = fileRequestStr.replaceAll(MD5, "");
fileRequestStr = fileRequestStr.substring(1, fileRequestStr.length());
fileName = fileRequestStr;//TODO:改了协议后要修改成下一行;
Log.i(TAG, "ReceiveFile 分割  =  " + "  MD5:  " + MD5 + " name = " + fileRequestStr);

方法二:

  1. (推荐)
  2. 事先创建一个较大的 byte[];我这里接收到的消息不会超过 80 个字,故我设置了80;
Socket name = ss.accept();
InputStream nameIPS = name.getInputStream();

//方法:丢前面两个数;且size之后都是乱码
StringBuffer tempName = new StringBuffer("");
byte[] bytes = new byte[80];
nameIPS.read(bytes);

/**
 * 解析获取到的文件信息;并分离出 MD5、Name 以及文件大小;
 */
String fileName = "";
String fileSize = "";

String bytesName = new String(bytes, code);
String MD5 = bytesName.substring(0, bytesName.indexOf("$"));
bytesName =  bytesName.replaceAll(MD5,"");//去掉MD5
bytesName = bytesName.substring(1, bytesName.length());//返回一个新字符串
fileName = bytesName.substring(0, bytesName.indexOf("$"));
fileSize = bytesName.replaceAll(fileName, "");
fileSize = fileSize.substring(1, fileSize.length());
//处理乱码(数组建的大,多余部分会形成乱码)
fileSize = fileSize.trim();

之所以如此,最主要的原因是 Java 和 C++ 之间的差异,不过最重要的是,对 C++ 的毫无了解,以及对 JAVA 基础的淡忘。