Unicode Byte sequence / конвертирует символ в байтовый массив - PullRequest
0 голосов
/ 05 июня 2011

Я пытаюсь написать простую программу для этого вопроса:

Напишите функцию, которая проверяет правильность последовательности байтов Юникода.Последовательность Unicode кодируется как: - первый байт указывает число последующих байтов. «11110000» означает 4 последовательных байта данных - байты данных начинаются с «10xxxxxx»

   public static void main(String[] args)
{

        System.out.println(checkUnicode(new byte[] {(byte)'c'}));

}

    /**
     * Write a function that checks for valid unicode byte sequence. A unicode
     * sequence is encoded as: - first byte indicates number of subsequent bytes
     * '1111000' means 4 subsequent data bytes - data bytes start with a
     * '10xxxxxx'
     * 
     * @param unicodeChar
     * @return
     */
 public static boolean checkUnicode(byte[] unicodeChar)
{
    byte b = unicodeChar[0];
    int len = 0;

    int temp = (int)b<<1;
    while((int)temp<<1 == 0)
    {
        len++;
    }
    System.out.println(len);

    if (unicodeChar.length == len) 
    {
        for(int i = 1 ; i < len; i++)
        {
            // Check if Most significant 2 bits in the byte are '10'
            // c0, in base 16, is 11000000 in binary
            // 10000000, in base 2, is 128 in decimal
            if( ( (int)unicodeChar[i]&0Xc0 )==128 )
            {
                continue;
            }
            else
            {
                return false;
            }
        }
        return true;
    }
    else
    {
        return false;
    }
}

The output I get is   
99
false  

Изменено преобразование с символьного на байтовый массив на основена комментарий Криса Джестера-Янга.

Может ли кто-нибудь указать мне правильное направление

Спасибо

Сделаны некоторые модификации, основанные на вкладе Теда Хоппа.
PS:
Я получил вопрос от некоторыхфорум, и я думаю, что он там не был правильно размещен, однако я все же решил решить его и использовать его как есть, чтобы не запутывать его больше, поскольку я тоже не совсем понял!

Ответы [ 4 ]

6 голосов
/ 05 июня 2011

Вот решение уровня предприятия для вашей работы уровня предприятия:

public static void main(String[] args) {
    if (args.length == 0 || args[0] == null || (args[0] = args[0].trim()).isEmpty()) {
        System.out.println("No argument passed or argument empty!");
        return;
    }

    String arg = args[0];
    System.out.println("arg: " + arg + ", arg len: " + arg.length());

    BitSet bs = new BitSet(arg.length());
    for (int i = 0; i < arg.length(); i++) {
        if (arg.charAt(i) == '1') {
            bs.set(i, true); 
        }
    }
    ByteBuffer bb = ByteBuffer.wrap(bs.toByteArray());
    Charset cs = Charset.forName("UTF-8");
    CharsetDecoder csd =
            cs.newDecoder().onMalformedInput(CodingErrorAction.REPORT).
            onUnmappableCharacter(CodingErrorAction.REPORT)
            ;

    try {
        CharBuffer cb = csd.decode(bb);
        String uns = cb.toString();
        System.out.println("Got unicode string of len " + uns.length() + ": " + uns + " from " + arg + " -- no errors!");
    } catch (CharacterCodingException cce) {
        System.out.println("Invalid UTF-8 unicode string! " + cce.getMessage());
    }
}

Проверка:

public static void test() {
    StringBuilder sb = new StringBuilder();
     byte[] byt = new String("stupid interview").getBytes();
     BitSet byt1 = fromByteArray(byt);
     for (int i = 0; i < byt1.size(); i++) {
         sb.append(byt1.get(i) ? "1" : "0");
     }
     String[] st = new String[1];
     st[0] = sb.toString();
     main(st);
}

public static BitSet fromByteArray(byte[] bytes) {
    BitSet bits = new BitSet();
    for (int i=0; i<bytes.length*8; i++) {
        if ((bytes[bytes.length-i/8-1]&(1<<(i%8))) > 0) {
            bits.set(i);
        }
    }
    return bits;
}

Выход:

11001110001011101010111000001110100101100010011000000100100101100111011000101110101001100100111001101110100101101010011011101110
arg: 11001110001011101010111000001110100101100010011000000100100101100111011000101110101001100100111001101110100101101010011011101110, arg len: 128
{0, 1, 4, 5, 6, 10, 12, 13, 14, 16, 18, 20, 21, 22, 28, 29, 30, 32, 35, 37, 38, 42, 45, 46, 53, 56, 59, 61, 62, 65, 66, 67, 69, 70, 74, 76, 77, 78, 80, 82, 85, 86, 89, 92, 93, 94, 97, 98, 100, 101, 102, 104, 107, 109, 110, 112, 114, 117, 118, 120, 121, 122, 124, 125, 126}
Got unicode string of len 16: stupid interview from 11001110001011101010111000001110100101100010011000000100100101100111011000101110101001100100111001101110100101101010011011101110 -- no errors!
1 голос
/ 05 июня 2011

Во-первых, документация UTF-8, представленная в вопросе, неверна. Не существует такой вещи, как «допустимая последовательность байтов Unicode» без указания кодировки. Безопасное предположение, что они имели в виду UTF-8. Второй (и более важный) 11110000 не указывает на еще 4 байта данных. Четыре "1" бита перед первым "0" битом указывают всего из 4 байтов (то есть 3 последовательных байта, а не 4, каждый из которых начинается с "10"). Правила хорошо описаны в статье Википедии о UTF-8 .

Во-вторых, преобразование символа в строку и вызов getBytes - это хороший подход, но вам необходимо указать кодировку в качестве аргумента для getBytes. (Однако для символа «с» это не будет иметь значения.)

Я не знаю, что вы пытаетесь сделать в своем коде, но вам нужно посчитать, сколько «1» битов перед первым «0» битом. Ваш код ничего подобного не делает.

ОБНОВЛЕНИЕ: На самом деле я бы не стал пытаться анализировать структуру битов. Я просто передаю байты в CharsetDecoder и проверяю, не засорился ли он:

public static boolean checkUnicode(byte[] unicodeChar)
{
    try {
        CharsetDecoder decoder = Charset.forName(UTF-8).newDecoder();
        // test only for malformed input, ignore unknown Unicode characters
        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
        decoder.onMalformedInput(CodingErrorAction.REPORT);
        decoder.decode(ByteBuffer.wrap(unicodeChar));
        return true;
    }
    catch (MalformedInputException ex)
    {
        return false;
    }
}
0 голосов
/ 05 июня 2011

Вы можете использовать Character.toCodePoint(), чтобы получить int, а затем от int до byte должно быть просто.

0 голосов
/ 05 июня 2011

Как конвертировать ваших персонажей в byte с, вы можете просто разыграть:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...