5

I want to compare the response from the server with a string, but I get a false result when testing the two strings. Why?

I found this but didn't help: How do I compare strings in Java?

I tried two ways:

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
String code;
if(Objects.equals((code = in.readLine()), "S")) { //Input string: "S"
    //code
}

 

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
String code;
if((code = in.readLine()).equals("S")) { //Input string: "S"
    //code
}

The code does not run in either case because the value of the test is false.

Full code

Server side - C# (Windows)

class ManagePhoneClients
    {
        public void managePhoneClients(object obj)
        {
            Boolean socketalive = true;
            TcpClient tcpClient = (TcpClient)obj;
            StreamReader sr = new StreamReader(tcpClient.GetStream(), Encoding.UTF8);
            StreamWriter sw = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
            Boolean isPhoneClientConnected = false;
            String user;
            String answer;
            String tl;
            List<string> LC = new List<string>();
            Boolean qss = false;
            Program program = new Program();
            Int32 points = 0;

            ConsoleMethods.writeLine("Thread started for the phone client.", "Info", ConsoleColor.Cyan);

            sw.WriteLine("S");
            sw.Flush();

            while (socketalive == true)
            {
                try
                {
                    if (Program.isMainClientConnected != true || Program.isPowerPointConnected != true)
                    {
                        ConsoleMethods.writeLine("Connection refused because the necessary clients are not connected!", "Error", ConsoleColor.Red);
                        sw.WriteLine("NS");
                        sw.Flush();
                        tcpClient.Close();
                        socketalive = false;
                    }
                    else
                    {
                        sw.WriteLine("LC");
                        sw.Flush();
                    }
                    if (isPhoneClientConnected != true & sr.Peek() != -1)
                    {
                        String rLC = sr.ReadLine();
                        LC.AddRange(rLC.Split('|'));
                        if (LC[1].ToString() == Program.passPhoneClient)
                        {
                            user = LC[0];
                            Program.userNames.Add(user);
                            ConsoleMethods.writeLine("Phone connected from: " + tcpClient.Client.RemoteEndPoint, "Info", ConsoleColor.Cyan);
                            sw.WriteLine("S");
                            sw.Flush();
                            Program.utnr = rLC;
                            isPhoneClientConnected = true;
                        }
                        else
                        {
                            sw.WriteLine("NS");
                            sw.Flush();
                            socketalive = false;
                            ConsoleMethods.writeLine("Phone client disconnected because the password was invalid!", "Error", ConsoleColor.Red);
                        }

                    }
                    switch (sr.ReadLine())
                    {
                        case "CLIENT-EXCEPTION":
                            ConsoleMethods.writeLine("Exception in phone client from: " + tcpClient.Client.RemoteEndPoint + "\n" + sr.ReadLine(), "Client-Error", ConsoleColor.DarkRed);
                            break;
                        case "RECEIVED_POINTS":
                            int point = int.Parse(sr.ReadLine());
                            points += point;
                            ConsoleMethods.writeLine("Phone client succesfully completed a task from: " + tcpClient.Client.RemoteEndPoint + " Point: " + point, "Client-Received Points", ConsoleColor.DarkRed);
                            ConsoleMethods.writeLine("Phone client collected points from: " + tcpClient.Client.RemoteEndPoint + " Points: " + points, "Client-Collected Points", ConsoleColor.DarkRed);
                            break;
                    }

                }
                catch (Exception e)
                {
                    tcpClient.Close();
                    socketalive = false;
                    ConsoleMethods.writeLine(e.Message + e.StackTrace + e.StackTrace, "Error", ConsoleColor.Red);
                }
            }
        }
    }

(This is not yet complete!)

Client side - Java (Android)

   public void login(View v) {
        final Context context = this;
        new Thread(new Runnable() {
            public void run() {
                try {
                    final Socket socket = new Socket("192.168.0.104", 90);
                    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF8"));
                    PrintWriter out = new PrintWriter(socket.getOutputStream());
                    out.print("P" + "\r\n");
                    out.flush();
                    String code;
                    code = in.readLine();
                    if(code.equals("S")) {
                        if (Objects.equals((code = in.readLine()), "LC")) {
                            out.print(((EditText)findViewById(R.id.username)).getText().toString() + "|" + ((EditText)findViewById(R.id.password)).getText().toString() + "\r\n");
                            out.flush();
                            if(Objects.equals((code = in.readLine()), "S")) {
                                new ServerContact(context).Listener(socket);
                                startActivity(new Intent(Login.this, Waiting.class));
                            } else {
                                throw new Exception("Login failed because the server refused the login request. Server responded with status code: '" + code + "'.");
                            }
                        } else {
                            throw new Exception("Login failed because the server refused the login request. Server responded with status code: '" + code + "'.");
                        }
                    } else {
                        throw new Exception("Login failed because the server refused the login request. Server responded with status code: '" + code + "'.");
                    }
                } catch (Exception e) {
                    new ExceptionWriter(e);
                }
            }
        }).start();
    }

(This is not yet complete!)

markspace
  • 10,621
  • 3
  • 25
  • 39
Noel Nemeth
  • 646
  • 11
  • 21
  • 3
    Well, the results suggest that the string you're getting back from `readLine` **isn't** `"S"`. So your best bet is to use the debugger built into your IDE to example the `code` variable and see what the actual content is. – T.J. Crowder Apr 07 '18 at 18:22
  • 1
    You might be getting non-printable characters. Use a debugger to inspect the contents of `code`. (Trivially, print its length). – Andy Turner Apr 07 '18 at 18:22
  • How do you know `code` is `"S"`? Maybe it has some zero-width characters? Convert the string to a char array and print the integer value of each char. – Sweeper Apr 07 '18 at 18:23
  • 1
    @Sweeper: Or...use a debugger? No need to stumble around in the dark with a `System.out.println` torch when you can turn on the lights. :-) – T.J. Crowder Apr 07 '18 at 18:24
  • @T.J.Crowder I didn't write it into the question, but in case of a false test it throws an exception that contains the `code` value. – Noel Nemeth Apr 07 '18 at 18:34
  • Well, what is the `code` value? Be careful too that `readLine()` can return null. – markspace Apr 07 '18 at 18:35
  • On the Windows side: You are passed in a `TcpClient` object that you then proceed to wrap? So someone could have already written the junk you are seeing on the Android side, even if you didn't write that stuff in this method yourself (see the comments on my answer below). – markspace Apr 07 '18 at 20:04
  • 1
    I think I managed to solve the problem. When I replaced `Ecoding.UTF8` with `new UTF8Encoding(false)`, the client has successfully completed all testing. – Noel Nemeth Apr 07 '18 at 20:19
  • So it was a BOM then. Sorry I didn't recognize it sooner. – markspace Apr 07 '18 at 20:43
  • Also, you may wish to add your own answer and mark it correct. That's the normal procedure in cases like this. – markspace Apr 07 '18 at 20:44

2 Answers2

1

I managed to solve it. On the server side I have to disable the BOM.

No BOM:

StreamWriter sw = new StreamWriter(tcpClient.GetStream(), new UTF8Encoding(false));

With BOM:

StreamWriter sw = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
Noel Nemeth
  • 646
  • 11
  • 21
0

It works for me (using your first case). I think we've all concluded that code is not in fact equal to "S", sorry about that.

public class EqualsTest {

   public static void main( String[] args ) throws IOException {
      MyStream socket = new MyStream( new ByteArrayInputStream( "S\n".getBytes() ));

      BufferedReader in = new BufferedReader( new InputStreamReader( socket.getInputStream(), "UTF8" ) );
      String code;
      if( Objects.equals( (code = in.readLine()), "S" ) ) { 
         System.out.println( "true" );
      } else {
         System.out.println( "false" );
      }
   }

   static class MyStream {
      private final InputStream ins;

      public MyStream( InputStream ins ) {
         this.ins = ins;
      }

      public InputStream getInputStream() {
         return ins;
      }

   }
}

Output:

run:
true
BUILD SUCCESSFUL (total time: 0 seconds)

I'll add some ideas for testing code for debugging:

     // how to debug
     System.err.println( "code="+code+" length="+code.length() );
     System.err.println( "code bytes="+Arrays.toString( code.getBytes() ) );
markspace
  • 10,621
  • 3
  • 25
  • 39
  • This is interesting ... Really doesn't match "S" with server's "S". `CODE = [-17, -69, -65, 83]` `S = [83]` – Noel Nemeth Apr 07 '18 at 19:00
  • I see an "S" at the end of your input (the 83) but you've obviously got some other junk in there. I think perhaps you may not be decoding UTF-8, it might be some other decoding. Possibly also there's a BOM in your input, though I didn't double check its values to be sure. – markspace Apr 07 '18 at 19:01
  • Is it possible that the problem is because the server is in C# while the client is running on java (Android)? Both sides have UTF-8 encoding. – Noel Nemeth Apr 07 '18 at 19:12
  • All UTF-8 should be the same. If you're running from a Windows machine, I think it's more likely that the input stream is cp-1252 and contains a BOM, though I admit it doesn't look like a BOM to me. – markspace Apr 07 '18 at 19:17
  • @NoelNemeth Or of course the C# code could be buggy/broken/doing the wrong thing. Try to get a precise spec of what *exactly* that part of the code does from whoever wrote it. If you have source, add it to your question above. – markspace Apr 07 '18 at 19:20
  • I added both the server and the client-side full code. – Noel Nemeth Apr 07 '18 at 19:52
  • @NoelNemeth The extra bytes (`-17, -69, -65`) are the byte encoding of the UTF-8 BOM (0xef, 0xbb, 0xbf). You need to tell your CS server to not send to UTF-8 BOM – Thomas Kläger Apr 08 '18 at 08:35