LoginSignup
3
1

More than 5 years have passed since last update.

Kotlinで同じ文字列が違うと判断されるバグを直す

Last updated at Posted at 2019-01-12

Qiita初投稿です。よろしくおねがいします。
C#ばかり書いていましたが最近Kotlinをはじめました。いいですよね、Kotlin。擬人化したら絶対に可愛いです。

UDP通信をしようとしたら困った

簡単な文字列を受信し、ByteArray->Stringに変換してコンソールに写すだけです。(通信に関しては今回は触れません)
で、"finish"という文字列を受信したら通信をやめる、そんな感じにしたかったんです。したかったんです。

同じ文字列なのに等しいと判断されない…

うまくいかなかったときのソースコードは以下の通りです。

Main.kt
import Mylib.Udp.UdpConnection //自作のUdp通信クラス
import java.nio.charset.Charset

fun main(args: Array<String>)
{
    val port = 2222
    val bufferSize = 16
    val udp = UdpConnection(port, bufferSize)
    var received: String? = null

    println("Start")
    while (received != "finish")
    {
        received = udp.receive().toString(Charset.defaultCharset())
        println(received)
    }
}
UdpConnection
package Mylib.Udp

import java.io.FileWriter
import java.io.PrintWriter
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.nio.charset.Charset

class UdpConnection(private val port: Int, private val bufferSize:Int)
{
    fun receive(): ByteArray
    {
        val socket= DatagramSocket(port)
        val data = ByteArray(bufferSize)
        var packet: DatagramPacket? = null
        try
        {
            packet = DatagramPacket(data, data.size)
            socket.receive(packet)
        }
        catch (e: Exception)
        {
            println(e.message)
        }
        socket.close()
        return data
    }
}


これを実行中に"fnish"と三回送ったとします。私としてはコンソールには"Start"の後に一度だけ"finish"と出てきて終わっていただきたい。しかし、結果は…

Start
finish          
finish          
finish          

?????????なんですか??これ
いや、まぁ、文字化けしてるとかならわかるんですよ。
最初はJavaで有名な"=="と"equals"の違いが原因かと思いました。しかし、Kotlinでは参照先の比較は"==="で値の比較は"=="となっているため、今回は関係なさそうです。他にも文字コードや送信機などを疑ってみましたがどれも見当違い…

結局どうしたか

まず、以下の拡張関数を定義しました。

fun ByteArray.createString(packet: DatagramPacket) = String(this, 0, packet.length, Charset.defaultCharset())

そして上記のreceiveメソッドの型をString?に変更し、リターン部分を下記のように変更しました。

return if (packet != null) data.createString(packet); else null

結果、意図していた動作をしましたが、なぜ前のコードがダメだったのかはわかりません(わかる方いらっしゃいましたらご教示ください)

最後に

初投稿のため、拙い部分やおかしな部分もあると思いますが、閲覧頂きありがとうございます。関係ないですが、C#では下記のように簡単に実装できたため、Udp通信のハローワールド的なプログラムでつまずくと思いませんでした…

using System;
using System.Net.Sockets;
using System.Text;
class Program
{
    static void Main(string[] args)
    {
        var Receiver = new UdpClient(2222);
        var ReceivedStr = string.Empty;
        Console.WriteLine("Start");
        while ((ReceivedStr = Encoding.UTF8.GetString(Receiver.ReceiveAsync().Result.Buffer)) != "finish")
            Console.WriteLine(ReceivedStr);
    }
}

ここまで言ってJavaの使いやすいUdpライブラリがあったら恥ずかしいですね。(でもあったら使いたいです)

3
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1