IT story

바이트 배열을 문자열로 변환하거나 그 반대로 변환하는 방법은 무엇입니까?

hot-time 2020. 4. 22. 08:12
반응형

바이트 배열을 문자열로 변환하거나 그 반대로 변환하는 방법은 무엇입니까?


안드로이드에서 바이트 배열을 문자열로 변환해야하지만 바이트 배열에 음수 값이 있습니다.

해당 문자열을 다시 바이트 배열로 변환하면 얻는 값이 원래 바이트 배열 값과 다릅니다.

적절한 전환을 얻으려면 어떻게해야합니까? 변환에 사용하는 코드는 다음과 같습니다.

// Code to convert byte arr to str:
byte[] by_original = {0,1,-2,3,-4,-5,6};
String str1 = new String(by_original);
System.out.println("str1 >> "+str1);

// Code to convert str to byte arr:
byte[] by_new = str1.getBytes();
for(int i=0;i<by_new.length;i++) 
System.out.println("by1["+i+"] >> "+str1);

나는이 문제에 갇혀있다.


바이트 배열에는 인코딩이 있어야합니다. 음수 값이있는 경우 인코딩은 ASCII 일 수 없습니다. 일단 파악하면 다음을 사용하여 바이트 세트를 문자열로 변환 할 수 있습니다.

byte[] bytes = {...}
String str = new String(bytes, "UTF-8"); // for UTF-8 encoding

사용할 수있는 인코딩이 많이 있습니다 .Sun javadocs 의 Charset 클래스를보십시오 .


사이의 "적절한 변환" byte[]하고 String명시 적으로 사용할 인코딩 상태입니다. a로 시작 byte[]하는데 실제로 텍스트 데이터가 포함되어 있지 않으면 "적절한 변환" 이 없습니다 . Strings는 텍스트, byte[]이진 데이터를위한 것이며, 실제로해야 할 유일한 일은 당신이 절대로 할 필요가 없다면, 그것들 사이에서 변환 피하는 것입니다.

String바이너리 데이터를 보유하기 위해 실제로 a 사용해야하는 경우 가장 안전한 방법은 Base64 인코딩 을 사용 하는 것입니다.


근본적인 문제는 당신이 무의식적으로 다음과 같은 문자 세트를 사용하고 있다는 것입니다.

 bytes != encode(decode(bytes))

일부 경우에. UTF-8은 이러한 문자 집합의 예입니다. 특히, 특정 바이트 시퀀스는 UTF-8에서 유효한 인코딩이 아닙니다. UTF-8 디코더가 이러한 시퀀스 중 하나를 만나면 문제가되는 바이트를 버리고 "이러한 문자 없음"에 대한 유니 코드 코드 포인트로 디코딩 할 수 있습니다. 당연히 문자를 바이트로 인코딩하려고하면 결과가 달라집니다.

해결책은 다음과 같습니다.

  1. 사용중인 문자 인코딩에 대해 명시하십시오. String.toByteArray, 명시 적 문자셋과 함께 String 생성자와 메소드를 사용하십시오 .
  2. 바이트 데이터에 올바른 문자 세트를 사용하십시오 (또는 모든 바이트 시퀀스가 ​​유효한 유니 코드 문자에 매핑되는 "Latin-1"과 같은 것).
  3. 당신의 바이트 (정말) 이진 데이터이고, 당신이 전송을 할 수 있도록하려면 / A "를 기반으로 텍스트"를 통해 그들을 수신 채널, Base64 인코딩 ... 같은 사용 뭔가 이 목적을 위해 설계되었습니다 .

우리 String는 배열 로 새로운 것을 만들어야합니다 : http://www.mkyong.com/java/how-do-convert-byte-array-to-string-in-java/

String s = new String(bytes);

결과 문자열의 바이트 수는 사용하는 문자 집합에 따라 다릅니다. String #을 호출하면 new String (bytes)과 new String (bytes, Charset.forName ( "utf-8"))과 new String (bytes, Charset.forName ( "utf-16"))은 모두 다른 바이트 배열을 갖습니다. getBytes () (기본 문자 집합에 따라 다름)


사용 new String(byOriginal)하고 다시 변환 byte[]사용 getBytes()이 보장하지 않습니다 byte[]동일한 값을. 이는를 호출하는 것입니다 StringCoding.encode(..)를 인코딩 할 StringCharset.defaultCharset(). 이 인코딩 중에 인코더는 알 수없는 문자를 바꾸고 다른 변경을 수행하도록 선택할 수 있습니다. 따라서을 사용 String.getBytes()하면 원래 생성자에 전달한 것과 동일한 배열이 반환되지 않을 수 있습니다.


문제가 발생한 이유 : 누군가가 이미 지정한대로 : byte []로 시작하고 실제로 텍스트 데이터를 포함하지 않으면 "적절한 변환"이 없습니다. 문자열은 텍스트를위한 것이고 byte []는 이진 데이터를위한 것이며, 실제로 할 수있는 유일한 방법은 꼭 필요한 경우가 아니면 변환하지 않는 것입니다.

pdf 파일에서 byte []를 만든 다음 String으로 변환 한 다음 String을 입력으로 사용하고 파일로 다시 변환하려고 할 때이 문제가 관찰되었습니다.

따라서 인코딩 및 디코딩 논리가 내가했던 것과 동일한 지 확인하십시오. 바이트 []를 Base64로 명시 적으로 인코딩하고 디코딩하여 파일을 다시 작성했습니다.

사용 사례 : 일부 제한으로 인해 전송 byte[]시도 request(POST)했으며 프로세스는 다음과 같습니다.

PDF 파일 >> Base64.encodeBase64 (byte []) >> 문자열 >> 요청 전송 (POST) >> 수신 문자열 >> Base64.decodeBase64 (byte []) >> 바이너리 생성

이것을 시도하고 이것은 나를 위해 일했다 ..

File file = new File("filePath");

        byte[] byteArray = new byte[(int) file.length()];

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            fileInputStream.read(byteArray);

            String byteArrayStr= new String(Base64.encodeBase64(byteArray));

            FileOutputStream fos = new FileOutputStream("newFilePath");
            fos.write(Base64.decodeBase64(byteArrayStr.getBytes()));
            fos.close();
        } 
        catch (FileNotFoundException e) {
            System.out.println("File Not Found.");
            e.printStackTrace();
        }
        catch (IOException e1) {
            System.out.println("Error Reading The File.");
            e1.printStackTrace();
        }

이것은 나를 위해 잘 작동합니다 :

String cd="Holding some value";

문자열에서 바이트 []로 변환 :

byte[] cookie = new sun.misc.BASE64Decoder().decodeBuffer(cd);

byte []에서 문자열로 변환 :

cd = new sun.misc.BASE64Encoder().encode(cookie);

private static String toHexadecimal(byte[] digest){
        String hash = "";
    for(byte aux : digest) {
        int b = aux & 0xff;
        if (Integer.toHexString(b).length() == 1) hash += "0";
        hash += Integer.toHexString(b);
    }
    return hash;
}

나는 대답에없는 것을 발견했습니다. 바이트 배열의 각 바이트를 문자로 캐스트하고 char 배열에 넣을 수 있습니다. 그런 다음 문자열은

new String(cbuf)
여기서 cbuf는 char 배열입니다. 다시 변환하려면 각 문자를 바이트로 캐스팅하여 바이트 배열에 넣는 문자열을 반복하십시오.이 바이트 배열은 첫 번째 배열과 같습니다.


public class StringByteArrTest {

    public static void main(String[] args) {
        // put whatever byte array here
        byte[] arr = new byte[] {-12, -100, -49, 100, -63, 0, -90};
        for (byte b: arr) System.out.println(b);
        // put data into this char array
        char[] cbuf = new char[arr.length];
        for (int i = 0; i < arr.length; i++) {
            cbuf[i] = (char) arr[i];
        }
        // this is the string
        String s = new String(cbuf);
        System.out.println(s);

        // converting back
        byte[] out = new byte[s.length()];
        for (int i = 0; i < s.length(); i++) {
            out[i] = (byte) s.charAt(i);
        }
        for (byte b: out) System.out.println(b);
    }

}


javax.xml.bind.DatatypeConverter 그것을해야합니다 :

byte [] b = javax.xml.bind.DatatypeConverter.parseHexBinary("E62DB");
String s = javax.xml.bind.DatatypeConverter.printHexBinary(b);

다음은 바이트 배열을 문자열로 변환하는 몇 가지 방법입니다. 나는 그들이 잘 작동하는지 테스트했습니다.

public String getStringFromByteArray(byte[] settingsData) {

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(settingsData);
    Reader reader = new BufferedReader(new InputStreamReader(byteArrayInputStream));
    StringBuilder sb = new StringBuilder();
    int byteChar;

    try {
        while((byteChar = reader.read()) != -1) {
            sb.append((char) byteChar);
        }
    }
    catch(IOException e) {
        e.printStackTrace();
    }

    return sb.toString();

}

public String getStringFromByteArray(byte[] settingsData) {

    StringBuilder sb = new StringBuilder();
    for(byte willBeChar: settingsData) {
        sb.append((char) willBeChar);
    }

    return sb.toString();

}

이 방법으로 바이트 배열을 문자열로 변환하는 데 성공했습니다.

public static String byteArrayToString(byte[] data){
    String response = Arrays.toString(data);

    String[] byteValues = response.substring(1, response.length() - 1).split(",");
    byte[] bytes = new byte[byteValues.length];

    for (int i=0, len=bytes.length; i<len; i++) {
        bytes[i] = Byte.parseByte(byteValues[i].trim());
    }

    String str = new String(bytes);
    return str.toLowerCase();
}

base64 인코딩은 안전하고 "올바른 대답"을 주장 할 수는 있지만 Java 바이트 배열을 Java String으로 /있는 그대로 변환하는 방법을 찾고 있습니다. 즉, 바이트 배열의 각 멤버는 인코딩 / 전송에 추가 공간이 필요하지 않고 String 대응 부분에 그대로 남아 있습니다.

8 비트 투명 인코딩을 설명하는 이 답변 은 나에게 매우 도움이되었습니다. 나는 ISO-8859-1base64 인코딩에 필요한 팽창 된 공간 요구없이 테라 바이트의 이진 데이터를 사용 하여 성공적으로 앞뒤로 변환 (이진 <-> 문자열)하기 때문에 사용 사례 인 YMMV에 안전합니다.

또한 실험해야 할시기와 설명에 도움이되었습니다 .


그래도

new String(bytes, "UTF-8")

올바른 UnsupportedEncodingException예외를 처리하도록 강제 처리합니다. Java 1.6부터 다른 배열을 다른 생성자로 사용하여 바이트 배열을 다음으로 변환 할 수 있습니다 String.

new String(bytes, StandardCharsets.UTF_8)

이것은 예외를 던지지 않습니다.

다시 변환하려면 다음을 수행해야합니다 StandardCharsets.UTF_8.

"test".getBytes(StandardCharsets.UTF_8)

다시 한 번 확인 된 예외를 처리하지 않아도됩니다.


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;    

private static String base64Encode(byte[] bytes)
{
    return new BASE64Encoder().encode(bytes);
}

private static byte[] base64Decode(String s) throws IOException
{
    return new BASE64Decoder().decodeBuffer(s);
}

두 변환 모두에서 8 비트 문자 집합을 지정하십시오. 예를 들어 ISO-8859-1.


String사용 에서 바이트를 읽고 바이트 데이터를 문자열로 변환하는 바이트 스트림 대신 문자 스트림으로 ByteArrayInputStream랩핑하십시오 BufferedReader.

package com.cs.sajal;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class TestCls {

    public static void main(String[] args) {

        String s=new String("Sajal is  a good boy");

        try
        {
        ByteArrayInputStream bis;
        bis=new ByteArrayInputStream(s.getBytes("UTF-8"));

        BufferedReader br=new BufferedReader(new InputStreamReader(bis));
        System.out.println(br.readLine());

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }
}

출력은 다음과 같습니다

Sajal은 좋은 소년입니다


작동 코드입니다.

            // Encode byte array into string . TemplateBuffer1 is my bytearry variable.

        String finger_buffer = Base64.encodeToString(templateBuffer1, Base64.DEFAULT);
        Log.d(TAG, "Captured biometric device->" + finger_buffer);


        // Decode String into Byte Array. decodedString is my bytearray[] 
        decodedString = Base64.decode(finger_buffer, Base64.DEFAULT);

간단한 for 루프를 사용하여 변환 할 수 있습니다.

public void byteArrToString(){
   byte[] b = {'a','b','$'};
   String str = ""; 
   for(int i=0; i<b.length; i++){
       char c = (char) b[i];
       str+=c;
   }
   System.out.println(str);
}

InputStream is = new FileInputStream("/home/kalt/Desktop/SUDIS/READY/ds.bin");
byte[] bytes = IOUtils.toByteArray(is);

문자열은 char (16 비트 부호없는)의 모음입니다. 따라서 음수를 문자열로 변환하면 번역에서 손실됩니다.


public class byteString {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        String msg = "Hello";
        byte[] buff = new byte[1024];
        buff = msg.getBytes("UTF-8");
        System.out.println(buff);
        String m = new String(buff);
        System.out.println(m);


    }

}

Base64를 사용하여 문제를 해결하십시오. 사용하기가 너무 쉽습니다. http://iharder.sourceforge.net/current/java/base64/

참고 URL : https://stackoverflow.com/questions/1536054/how-to-convert-byte-array-to-string-and-vice-versa

반응형