Я хочу сравнить ответ от сервера с нить, но при тестировании двух строк получаю ложный результат. Почему?
Я нашел это, но не помогло: Как сравнить строки в Java?
Я пробовал два способа:
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
}
Код не запускается ни в том, ни в другом случае, потому что значение теста - ложный.
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);
}
}
}
}
(Это еще не закончено!)
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();
}
(Это еще не закончено!)
Возможно, вы получаете непечатаемые символы. Используйте отладчик для проверки содержимого code. (Тривиально выведите его длину).
Как узнать, что code - это "S"? Может, в нем есть какие-то символы нулевой ширины? Преобразуйте строку в массив символов и выведите целочисленное значение каждого символа.
@Sweeper: Или ... использовать отладчик? Когда вы можете включить свет, вам не нужно спотыкаться в темноте с фонариком System.out.println. :-)
@ T.J.Crowder Я не вписывал это в вопрос, но в случае ложного теста выдает исключение, содержащее значение code.
Ну и какова стоимость code? Также будьте осторожны, readLine() может вернуть null.
На стороне Windows: вам передается объект TcpClient, который вы затем оборачиваете? Таким образом, кто-то мог уже написать мусор, который вы видите на стороне Android, даже если вы сами не писали это в этом методе (см. Комментарии к моему ответу ниже).
Думаю, мне удалось решить проблему. Когда я заменил Ecoding.UTF8 на new UTF8Encoding(false), клиент успешно завершил все испытания.
Так что тогда это была спецификация. Извини, что не узнал раньше.
Кроме того, вы можете добавить свой ответ и отметить его правильным. Это нормальная процедура в подобных случаях.




У меня работает (используя ваш первый случай). Я думаю, мы все пришли к выводу, что code на самом деле не равен "S", извините за это.
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;
}
}
}
Выход:
run:
true
BUILD SUCCESSFUL (total time: 0 seconds)
Добавлю несколько идей по тестированию code для отладки:
// how to debug
System.err.println( "code = "+code+" length = "+code.length() );
System.err.println( "code bytes = "+Arrays.toString( code.getBytes() ) );
Это интересно ... На самом деле "S" не совпадает с серверной "S". CODE = [-17, -69, -65, 83]S = [83]
Я вижу букву «S» в конце вашего ввода (83), но у вас явно есть какой-то другой мусор. Я думаю, возможно, вы не декодируете UTF-8, это может быть какое-то другое декодирование. Возможно, в вашем вводе также есть спецификация, хотя я дважды не проверял ее значения, чтобы быть уверенным.
Возможно ли, что проблема в том, что сервер находится на C#, а клиент работает на java (Android)? Обе стороны имеют кодировку UTF-8.
Все UTF-8 должны быть одинаковыми. Если вы работаете на машине с Windows, я думаю, что более вероятно, что входной поток - это cp-1252 и содержит спецификацию, хотя я признаю, что для меня это не похоже на спецификацию.
@NoelNemeth Или, конечно, код C# мог быть ошибочным / сломанным / делать неправильные вещи. Попытайтесь получить точную спецификацию того, что точно делает эта часть кода, от того, кто ее написал. Если у вас есть источник, добавьте его в свой вопрос выше.
Я добавил как серверный, так и клиентский полный код.
@NoelNemeth Дополнительные байты (-17, -69, -65) - это байтовая кодировка спецификации UTF-8 (0xef, 0xbb, 0xbf). Вам необходимо указать серверу CS не отправлять в UTF-8 спецификацию.
Мне удалось это решить. На стороне сервера я должен отключить спецификацию.
Нет спецификации:
StreamWriter sw = new StreamWriter(tcpClient.GetStream(), new UTF8Encoding(false));
Со спецификацией:
StreamWriter sw = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
Вы должны отметить этот ответ как правильный, если это решение.
@markspace Я знаю, но мне нужно подождать 48 часов после публикации ответа.
Ах, тогда моя ошибка. Извини за это.
Что ж, результаты показывают, что строка, которую вы получаете от
readLine, не"S". Поэтому лучше всего использовать отладчик, встроенный в вашу среду IDE, на примере переменнойcodeи посмотреть, каково реальное содержимое.