3

I need to write code that does the following:

  1. Connect to a tcp socket
  2. Read a line ending in "\r\n" that contains a number N
  3. Read N bytes
  4. Use those N bytes

I am currently using the following code:

val socket = new Socket(InetAddress.getByName(host), port)
val in = socket.getInputStream;
val out = new PrintStream(socket.getOutputStream)

val reader = new DataInputStream(in)
val baos = new ByteArrayOutputStream
val buffer = new Array[Byte](1024)

out.print(cmd + "\r\n")
out.flush

val firstLine = reader.readLine.split("\\s")

if(firstLine(0) == "OK") {
  def read(written: Int, max: Int, baos: ByteArrayOutputStream): Array[Byte] = {
    if(written >= max) baos.toByteArray
    else {
      val count = reader.read(buffer, 0, buffer.length)
      baos.write(buffer, 0, count)
      read(written + count, max, baos)
    }
  }

  read(0, firstLine(1).toInt, baos)
} else {
  // RAISE something
}

baos.toByteArray()

このコードの問題は、 を使用するとDataInputStream#readLine非推奨の警告が発生することですが、 と の両方を実装するクラスが見つかりませread(...)readLine(...)BufferedReaderたとえば、実装しますreadが、Bytes ではなく Chars を読み取ります。これらの文字をバイトにキャストできますが、安全ではないと思います。

このようなものをscalaで書く他の方法はありますか?

ありがとうございました

4

3 に答える 3

0

これが私が見つけることができる最良の解決策のようです:

val reader = new BufferedReader(new InputStreamReader(in))
val buffer = new Array[Char](1024)

out.print(cmd + "\r\n")
out.flush

val firstLine = reader.readLine.split("\\s")

if(firstLine(0) == "OK") {
  def read(readCount: Int, acc: List[Byte]): Array[Byte] = {
    if(readCount <= 0) acc.toArray
    else {
      val count = reader.read(buffer, 0, buffer.length)
      val asBytes = buffer.slice(0, count).map(_.toByte)

      read(readCount - count, acc ++ asBytes)
    }
  }

  read(firstLine(1).toInt, List[Byte]())
} else {
  // RAISE
}

つまりbuffer.map(_.toByte).toArray、エンコーディングを気にせずに char 配列を Byte 配列に変換するために使用します。

于 2013-05-21T08:46:47.907 に答える