Проблема в преобразовании байтового массива в строку - PullRequest
0 голосов
/ 11 декабря 2018

Я пытаюсь преобразовать байтовый массив в строку HEX.Ниже приведен метод преобразования байтов в строки:

public static String toHexString(byte[] bytes) {
    char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for ( int j = 0; j < bytes.length; j++ ) {
        v = bytes[j] & 0xFF;
        hexChars[j*2] = hexArray[v/16];
        hexChars[j*2 + 1] = hexArray[v%16];
    }
    return new String(hexChars);
}

Проблема в том, что данные, отправляемые отправителем, выглядят примерно так:

00 4A 60 01 02 03 04 02 1030 38 00 00 0E 80 02 00 00 00 00 00 00 00 00 31 00 00 46 74 16 54 28 12 11 38 33 34 35 31 36 30 30 34 36 37 34 31 36 35 34 32 39 30 30 36 32 37 30 3535 32 34 00 12 91 0A 59 21 8C DA FB BC D2 52 00 14

и то, что я получаю после преобразования, выглядит примерно так:

00 4A 6001 02 03 04 02 10 30 38 00 00 0E EF BF BD 02 00 00 00 00 00 00 00 00 31 00 00 46 74 16 54 28 12 11 38 33 34 35 31 36 30 30 34 36 37 34 31 36 35 34 3239 30 30 36 32 37 30 35 35 32 34 00 12 EF BF BD

, хотя большая часть данных похожа, но данные "EFBFBD" поступают каким-то образом.

ОБНОВЛЕНИЕ

Полный код, необходимый для оценки проблемы:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

public class TCPClient {

private static final String TAG = "TCPRequest";

public static final String SERVER_IP = "X.X.X.X"; //server IP address
public static final int SERVER_PORT = xxxx;

private String mServerMessage;
// sends message received notifications
private OnMessageReceived mMessageListener = null;
// while this is true, the server will continue running
private boolean mRun = false;
// used to send messages
private OutputStream mOutStream;

private InputStream mInStream;

// used to read messages from the server
private BufferedReader mBufferIn;

byte[] bMsg = new byte[100];
int byteArr;

/**
 * Constructor of the class. OnMessagedReceived listens for the messages received from server
 */
public TCPClient(OnMessageReceived listener) {
    mMessageListener = listener;
}

/**
 * Sends the message entered by client to the server
 *
 * @param message text entered by client
 */
public void sendMessage(final String message) {
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if (mOutStream != null) {
                try {

                    byte[] bMessage = BytesUtil.hexStringToByteArray(message);
                    mOutStream.write(bMessage, 0, bMessage.length);
                    mOutStream.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    Thread thread = new Thread(runnable);
    thread.start();
}

/**
 * Close the connection and release the members
 */
public void stopClient() throws IOException {

    mRun = false;

    if (mOutStream != null) {
        mOutStream.flush();
        mOutStream.close();
    }

    mMessageListener = null;
    mServerMessage = null;

    mOutStream = null;
    mInStream = null;
}

public void run() {

    mRun = true;

    try {
        //here you must put your computer's IP address.
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

        PrintLog.log("TCP Client", "C: Connecting...");

        //create a socket to make the connection with the server
        //Socket socket = new Socket(SERVER_IP, SERVER_PORT);
        Socket socket = new Socket();
        socket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), 100000);

        sendMessage("requestData");

        if (socket.isConnected()) {
            PrintLog.log("CONNECTED...");
        } else {
            PrintLog.log("NOT CONNECTED: ");
        }

        try {

            //sends the message to the server
            mOutStream = socket.getOutputStream();

            //receives the message which the server sends back
            mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            //in this while the client listens for the messages sent by the server
            while (mRun) {

                bMsg = mBufferIn.readLine().getBytes();

                PrintLog.log(TAG, "Byte Array Response (Local): " + toHexString(bMsg));

                mServerMessage = new String(bMsg);

                PrintLog.log(TAG, "Listening message...");
                if (mServerMessage != null && mMessageListener != null) {
                    //call the method messageReceived from MyActivity class
                    mMessageListener.messageReceived(mServerMessage);
                }
            }

            PrintLog.log("RESPONSE FROM SERVER", "S: Received Message: '" + String.valueOf(mServerMessage) + "'");

        } catch (Exception e) {
            PrintLog.log("TCP", "S: Error" + e);
        } finally {
            //the socket must be closed. It is not possible to reconnect to this socket
            // after it is closed, which means a new socket instance has to be created.
            socket.close();
        }

    } catch (Exception e) {
        PrintLog.log("TCP", "C: Error" + e);
    }

}

public static String toHexString(byte[] bytes) {
    char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for ( int j = 0; j < bytes.length; j++ ) {
        v = bytes[j] & 0xFF;
        hexChars[j*2] = hexArray[v/16];
        hexChars[j*2 + 1] = hexArray[v%16];
    }
    return new String(hexChars);
}

//Declare the interface. The method messageReceived(String message) will must be implemented in the Activity
//class at on AsyncTask doInBackground
public interface OnMessageReceived {
    public void messageReceived(String message);
}

static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

}

Пожалуйста, помогите мне решить эту проблему.

Спасибо ввперед.

1 Ответ

0 голосов
/ 11 декабря 2018

String и char (2 байта UTF-16) содержат Unicode текст (в зависимости от языка).Следовательно, преобразование между byte[] - двоичными данными - и String всегда включает в себя кодировку и, возможно, повреждение или сбой преобразования.

Вышеприведенное может быть исправлено однобайтовымкодировка, например, Latin-1:

new String(hexChars, "ISO-8859-1");

Однако она занимает вдвое больше памяти (char - 2 байта), в основном медленнее (конвертирует байты) и небезопасна.

Ваша версия принимает значение по умолчаниюкодирование платформы, UTF-8, и может работать с необратимыми байтовыми последовательностями, поскольку UTF-8 является очень строгим форматом.

Ошибка заключается в другом коде.

Может быть в getBytes без кодировки:

byte[] bytes = string.getBytes("ISO-8859-1");

Лучше всего переписать код, чтобы он оставался с byte[] / ByteArrayOutputStream.


После ввода кода ввода / вывода:

Неудачные исправления будут:

        mBufferIn = new BufferedReader(
                new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));

        bMsg = mBufferIn.readLine().getBytes("ISO-8859-1");

Проблема в том, что может быть прочитана очень длинная строкаи что разделитель строк удаляется (CR, LF, NEL).

Таким образом, код должен быть более неопределенным:

        // receives the message which the server sends back
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        IOUtils.copy(socket.getInputStream(), baos);
        byte[] content = baos.toByteArray();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...