Страницы

Поиск по вопросам

Показаны сообщения с ярлыком byte. Показать все сообщения
Показаны сообщения с ярлыком byte. Показать все сообщения

пятница, 31 января 2020 г.

Получение битов из байтов

#java #android #byte #bit


Например есть 8 байт данных.
Есть стартовый байт и стартовый бит - откуда нужно взять информацию, а также длина
в битах(сколько нужно взять).

Как я могу достать из этих 8 байт например, с первого байта - 7 и 8 бит (т.е. стартовый
байт №1, позиция стартового бита №7, длина 2 бита)

или например, с 3го бита второго байта взять 14 бит (то есть используется второй
и третий байт)
    


Ответы

Ответ 1



Для того чтобы не "воевать" самому с битовыми операциями, можно воспользоваться стандартным классом BitSet: public static BitSet getBitSet(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) { BitSet arrayBitSet = BitSet.valueOf(array); int fromIndex = fromByteIndex * 8 + fromByteBitIndex; return arrayBitSet.get(fromIndex, fromIndex + bitsCount); } И использование: byte[] array = { 10, 1, 127 }; BitSet result = getBitSet(array, 1, 7, 2); System.out.println(result.get(0)); System.out.println(result.get(1)); false true В BitSet индексы битов определяются так: 10 = 00001010 76543210 - индексы Если нужен обратный порядок: 10 = 00001010 01234567 - индексы то, как вариант, можно предварительно менять порядок битов в байтах: public static BitSet getBitSet(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) { byte[] reversedBitsOrderArray = new byte[array.length]; for (int i = 0; i < array.length; i++) { reversedBitsOrderArray[i] = reverseBitsOrder(array[i]); } BitSet arrayBitSet = BitSet.valueOf(reversedBitsOrderArray); int fromIndex = fromByteIndex * 8 + fromByteBitIndex; return arrayBitSet.get(fromIndex, fromIndex + bitsCount); } private static byte reverseBitsOrder(byte b) { byte from = b; byte to = 0; for (int i = 0; i < 8; i++) { to <<= 1; to |= (from & 1); from >>= 1; } return to; } В принципе, в этом случае решение "взять биты вручную" становится короче и проще: public static boolean[] getBits(byte[] array, int fromByteIndex, int fromByteBitIndex, int bitsCount) { boolean[] bits = new boolean[bitsCount]; int fromIndex = fromByteIndex * 8 + fromByteBitIndex; for (int i = 0; i < bitsCount; i++) { int byteIndex = (i + fromIndex) / 8; int bitIndex = (i + fromIndex) % 8; bits[i] = (array[byteIndex] & (1 << (7 - bitIndex))) != 0; } return bits; }

Ответ 2



Как это устроено "под капотом": public static boolean getBitFromByte(byte b, int position) { // position = 6 - т.е. хотим получить 7 бит // 11010110 - b // & - побитовая операция И // 01000000 == (1 << 6) - сдвиг влево на 6 позиций (битов) // = // 01000000 // затем сдвигаем обратно на 6 позиций вправо: // 01000000 >> 6 == 00000001 - что означает 7-й бит // данного байта b равен 1 (единице) return ((b & (1 << position)) >> position) == 1; } public static boolean getBitFromBytes(byte[] bs, int bytePos, int bitPos) { return getBitFromByte(bs[bytePos], bitPos); } public static byte setBitInByte(byte b, boolean bit, int position) { if (bit) return (byte)(b | (1 << position)); else return (byte)(b & ~(1 << position)); } // почему-то нельзя преобразовать в Java тип boolean к int, не используя условие // поэтому приходится передавать установочный бит в типе int public static byte setBitInByteFast(byte b, int bit, int position) { return (byte) (((1 - bit) * ~0) ^ ((((1 - bit) * ~0) ^ b) | (1 << position))); } public static void main( String[] args ) { byte b = 0; b = setBitInByte(b, true, 3); System.out.println(getBitFromByte(b, 3)); b = setBitInByte(b, false, 3); System.out.println(getBitFromByte(b, 3)); b = setBitInByteFast(b, 1, 3); System.out.println(getBitFromByte(b, 3)); b = setBitInByteFast(b, 0, 3); System.out.println(getBitFromByte(b, 3)); }

Ответ 3



Используйте побитовый AND: byte[] bytes = {-1,2,3,4,5,6,7,8}; System.out.println((bytes[0] & 0x80) == 0x80); // 0x80 - 1000 0000 в двоичном коде System.out.println((bytes[0] & 0x40) == 0x40); // 0x40 - 0100 0000 в двоичном коде Результат: true true

среда, 29 января 2020 г.

Как привести массив byte[] к виду CharSequence?

#java #массивы #char #byte


Нужно написать класс AsciiCharSequence, который реализует хранение последовательности
ASCII-символов в массиве байт. По сравнению с классом String, хранящим каждый символ
как char, AsciiCharSequence будет занимать меньше памяти.

Класс AsciiCharSequence должен:


реализовывать интерфейс java.lang.CharSequence;
иметь конструктор, принимающий массив байт;
определять методы length(), charAt(), subSequence() и toString()


Ну вот я почти написал: 

public class AsciiCharSequence implements CharSequence {

     byte[] a1;

  public AsciiCharSequence(byte[] a){  //Конструктор класса
        a = this.a1;
    }

    @Override
    public String toString() {    //Переопределение toString()
        return "AsciiCharSequence{" +
                "a1=" + Arrays.toString(a1) +
                '}';
    }

    @Override
    public int length(){
        return a1.length;
    }; //Переопределение length()

    @Override
    public char charAt(int index){      //Переопределение charAt()
        char t000 = (char)a1[index];
        return t000;
    }

    @Override
    public CharSequence subSequence(int start, int end){  //Переопределение subSequence()
        CharSequence buf[] = new CharSequence[end - start];

       for(int i=start; i<=end;i++)
       {
           byte t = a1[i-start];
          buf[i]=(CharSequence)t;
       }
         return buf[end -start];
    }
}


Самый проблемный участок = Переопределение subSequence(). Это последние 12 строчек
с конца. Проблема такая: я никак не могу написать код, чтобы метод возвращал корректный
тип (CharSequence?). Если алгоритм формирования массива более-менее понятен, то преобразование
массива byte[] в CharSequence совсем не ясен. Сам метод должен применяться на массив
символов и возвращать массив символов с индексами лежащими от start до end. К примеру, 

String s0 = "Вова и Дима козлы";
   s0.subSequence(14,16) 


Должен возвращать "злы". 
    


Ответы

Ответ 1



Просто создайте новый экземпляр своего типа: @Override public CharSequence subSequence(int start, int end){ //Переопределение subSequence() return new AsciiCharSequence(Arrays.copyOfRange(a1, start, end)); } Заметьте, что toString() вы переопределили неправильно. В документации ясно сказано: String toString() Returns a string containing the characters in this sequence in the same order as this sequence. The length of the string will be the length of this sequence. То есть если вы переопределяете интерфейс CharSequence, вы обязаны вернуть в toString() строку, которая соответствует содержимому вашего CharSequence. Сделать это несложно: @Override public String toString() { //Переопределение toString() return new String(a1, java.nio.charset.StandardCharsets.ISO_8859_1); }

Ответ 2



Можно переписать класс в таком виде: public class AsciiCharSequence implements CharSequence { private byte[] data; public AsciiCharSequence(byte[] data) { this.data = data; } @Override public int length() { return data.length; } @Override public char charAt(int index) { return (char) (data[index] & 0xff); } @Override public CharSequence subSequence(int start, int end) { int length = end - start; byte[] bytes = new byte[length]; for (int i = 0, j = start; i < length; i++, j++) { bytes[i] = data[j]; } return new AsciiCharSequence(bytes); } @Override public String toString() { return new String(data); } } Дернуто с гитхаба. Автор - Михаил Валейко.

суббота, 4 января 2020 г.

Битовая математика

#c_sharp #инспекция_кода #byte


Программа читает бинарные данные из файла. У меня был пример чтения, на основе которого,
я реализовал данный пример записи.Общий смысл: есть заголовок файла (это код до слов
"пишем данные"). С заголовком все просто. Пишется без всяких преобразований. Далее
пишется маска и после маски пишутся 3 значения переменных. В маску пишется сколько
байт каждое из чисел занимает.

Код:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void ConnectButton_Click(object sender, RoutedEventArgs e)
    {
        // Переменная хранит путь к файлу
        string file_path = "ResultFile.rls";

        // Удаляем файл, если он есть
        if (File.Exists(file_path))
        {
            File.Delete(file_path);
        }

        // Создаем файл
        FileStream fs = File.Open(file_path, FileMode.OpenOrCreate, FileAccess.Write,
FileShare.Write);
        // Поток для записи в файл
        BinaryWriter bw = new BinaryWriter(fs);

        // Пишем размерность. Double
        bw.Write(-1.0);
        // Пишем какую то хрень. int32. 
        bw.Write(2);
        // Количество записей. int32. 
        bw.Write(5);
        // Val1. Double
        bw.Write(6800.0);
        // Val2. Double
        bw.Write(6800.0);
        // Val3. Double
        bw.Write(6800.0);
        // Val4 Double
        bw.Write(6800.0);
        // DateTime. Int64
        bw.Write(new DateTime(2015, 03, 12, 23, 0, 0).Ticks);
        // Val5. Int64
        bw.Write((Int64)2);

        // пишем данные
        AddItem(bw, 5, 10, 0);
        AddItem(bw, 1, 0, 1);
        AddItem(bw, 3, 20, 3);
        AddItem(bw, 5, 60, 1);
        AddItem(bw, 4, 80, 2);

        bw.Close();
        fs.Close();
    }

    // Функция отрезает не значимые значения массива
    byte[] CutZero(byte[] in_array)
    {
        // Список байт
        List result;
        // Инициализируем список
        result = new List();

        // Переменная определяет, что пора начинать копирование
        bool ready_to_copy = false;

        // В цикле перебираем каждый байт переданного массива с конца
        for (int i = in_array.Length - 1; i >= 0; i--)
        {
            // Если это не нулевой байт, то начинаем копирование
            if (in_array[i] != 0x00)
            {
                ready_to_copy = true;
            }

            // Если копирование началось
            if(ready_to_copy)
            {
                result.Add(in_array[i]);
            }
        }

        // Возвращаем полученный массив
        return result.ToArray();
    }

    // Добавить данные в файл
    private void AddItem(BinaryWriter _bw, int _vol, int _dp, int _dt)
    {
        // 1.Считаем переменные
        // 1.1. Val1
        byte[] vol = CutZero(BitConverter.GetBytes(_vol));
        // 1.2. Val2
        byte[] dp = CutZero(BitConverter.GetBytes(ConvertVal2Bytes(_dp)));
        // 1.3. Val3
        byte[] dt = CutZero(BitConverter.GetBytes(_dt));

        // 1. Количество байт. Сразу пишем в двоичном виде
        string str_length = "0";
        // 1.1. Для Val1
        str_length += ConvertFromVal1(vol.Length);
        // 1.2. Для Val2
        str_length += ConvertFromVal2(dp.Length);
        // 1.3. Для Val3
        str_length += ConvertFromVal3(dt.Length);

        // Пишем маску
        _bw.Write(Convert.ToByte(str_length, 2));

        // Val3
        _bw.Write(dt);
        // Val2
        _bw.Write(dp);
        // Val1
        _bw.Write(vol);
    }

    // Конвертируем байты
    private byte ConvertVal2Bytes(int _dp)
    {
        byte result;
        // Получим массив байт, для определения длины
        byte[] dp = CutZero(BitConverter.GetBytes(_dp));

        // В зависимости от количества байт добавляем дельты
        switch (dp.Length)
        {
            case 0:
            {
                // Ничего не добавляем
                result = (byte)_dp;
                break;
            }
            case 1:
                {
                    result = (byte)((byte)_dp + 0x80);
                    break;
                }
            case 2:
                {
                    result = (byte)((byte)_dp + 0x400);
                    break;
                }
            case 4:
                {
                    result = (byte)((byte)_dp + 0x4000000);
                    break;
                }
            default:
                {
                    result = (byte)_dp;
                    break;
                }
        }

        // Возвращаем результат
        return result;
    }

    // Конвертируем длину в двоичное представление
    private string ConvertFromVal3(int length)
    {
        string result = "";

        switch (length)
        {
            case 0:
                result = "00";
                break;
            case 1:
                result = "01";
                break;
            case 2:
                result = "10";
                break;
            case 3:
                result = "11";
                break;
            default:
                break;
        }

        return result;
    }
    // Конвертируем длину в двоичное представление
    private string ConvertFromVal2(int length)
    {
        string result = "";

        switch (length)
        {
            case 0:
                result = "00";
                break;
            case 1:
                result = "01";
                break;
            case 2:
                result = "10";
                break;
            case 4:
                result = "11";
                break;
            default:
                break;
        }

        return result;
    }
    // Конвертируем длину в двоичное представление
    private string ConvertFromVal1(int length)
    {
        string result = "";

        switch (length)
        {
            case 1:
                result = "001";
                break;
            case 2:
                result = "110";
                break;
            case 4:
                result = "111";
                break;
            case 8:
                result = "010";
                break;
            default:
                break;
        }

        return result;
    }
}


Все работает. Но у меня есть такое ощущение, что можно как то это упростить. Я не
работал ни разу с байтами / битами. Возможно часть кода можно заменить какими то стандартными
функциями. Очень было бы поучительно.
    


Ответы

Ответ 1



Например, функцию CutZero можно представить на LINQ так: IEnumerable CutZero(IEnumerable in_array) { return in_array.Reverse().SkipWhile(b => b == 0x00); } Затем, код (byte)((byte)_dp + 0x400) выглядит странно: прибавление 0x400 не затрагивает младший байт, так что после преобразования к (byte) он всё равно отбросится. Затем, ConvertFromVal3 — это перевод в двоичное представление? Его можно легко заменить на встроенную функцию: Convert.ToString(length, 2).PadLeft(2, '0') Затем, совершенно неясно, что делают функции ConvertFromVal2 и ConvertFromVal1. Они не конвертируют в двоичное представление (т. к., например, двоичное представление для 4 будет никак не "111"), но возвращают явно двоичные строки. Затем, конвертация чисел в строку лишь для того, чтобы потом склеить и сконвертировать назад, выглядит как-то совсем странно. Если вы хотите склеить биты, применяйте битовые операции: private byte ConvertFromVal3(int length) { if (length < 0 || length > 3) throw new ArgumentException(...); return (byte)length; } private byte ConvertFromVal2(int length) { switch (length) { case 0: return (byte)0; case 1: return (byte)1; case 2: return (byte)2; case 4: return (byte)3; default: throw new ArgumentException(...); } } private byte ConvertFromVal1(int length) { switch (length) { case 1: return (byte)1; case 2: return (byte)6; case 4: return (byte)7; case 8: return (byte)2; default: throw new ArgumentException(...); } } // ... // 1. Количество байт. Сразу пишем в двоичном виде byte lengths = 0; // 1.1. Для Val1 lengths |= (ConvertFromVal1(vol.Length) << 4); // 1.2. Для Val2 lengths |= (ConvertFromVal2(dp.Length) << 2); // 1.3. Для Val3 lengths |= ConvertFromVal3(dt.Length); // Пишем маску _bw.Write(lengths);

Ответ 2



Если под упростить подразумевается уменьшение количества строк кода, то можно в ConnectButton_Click вместо многократных bw.Write(...) значения поместить в массив и вывести их в цикле. А ConvertFromVal3, например, определить так: private string ConvertFromVal3(int length) { var arr = new[] { "00", "01", "10", "11" }; return length < arr.Length ? arr[length] : ""; }

четверг, 26 декабря 2019 г.

int на byte стоит ли?

#java #переменные #byte #перевод #int


Говорят что все равно машина заменяет byte на int так как ей лучше работать с Int,
если заменить все int на byte потребление ресурсов будет меньше ? 
    


Ответы

Ответ 1



В стандартном C/С++ никакая операция не может выполняться с типом меньше int. Если char, byty или short меньше, чем int на текущей платформе, они неявно повышаются до int. Компилятор должен сделать это неявное продвижение, там нет пути вокруг него, не нарушая стандарт. Никакая операция с целочисленными значения (добавление, побитовое, логическое и т.д. и т.д.) в языке не может выполняться на меньшем целочисленном типе, чем int. Таким образом, операции с byte/char/short/int(и другими), как правило, одинаково быстры, так как первые повышаются до последнего. На 32-битном процессоре, более мелкие типы медленнее, потому что он хочет, чтобы все было аккуратно выровнено в 32-битных кусках. 32-битные компиляторы обычно оптимизируют скорость и выделяют меньшие целые типы в большем пространстве, чем указано. Хотя обычно меньшие целые типы, конечно, занимают меньше места, чем более крупные, поэтому, если вы планируете оптимизировать размер ОЗУ, то предпочительнее использовать, те типы в диапазон, которых входят значения.

вторник, 24 декабря 2019 г.

Перевод числа в массив байтов

#java #byte


Как представить число (int, float) в виде массива байтов в Java?
    


Ответы

Ответ 1



Для этого можно воспользоваться ByteBuffer-ом: int value = 100000; byte[] bytes = ByteBuffer.allocate(4).putInt(value).array(); и float floatValue = 100.5f; byte[] floatBytes = ByteBuffer.allocate(4).putFloat(floatValue).array();

воскресенье, 15 декабря 2019 г.

Байты - перевод из строки

#python #python_3x #byte


data = "Hello".encode("utf-8") # перевод в байты


не могу разобраться в байтах... как бы я не старался, Python мне выдает b'Hello'...
как мне получить исходные байты этой строки?

Если попробовать с кириллицей, то все получается:

    data = "Привет".encode("utf-8") # b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'


или я не имею представления о байтах?  объясните пожалуйста
    


Ответы

Ответ 1



Как b'Hello' так и b'\xd0\x9f\xd1\x80...' принадлежат к одному типу bytes. b'Hello' == b'\x48\x65\x6c\x6c\x6f'. Байты, которые соответствуют печатаемым ascii символам (0x20..0x7e), по умолчанию показаны как эти символы в текстовом представлении repr(data) -- синтаксис, используемый для bytes-конcтант в исходном коде Питона (eval(repr(data)) == data). Использование символов для некоторых байтов вместо шестнадцатеричных кодов может вводить в заблуждение (как в этом случае). Легко получить hexdump, если необходимо: >>> b'Hello'.hex() '48656c6c6f' Мотивация по использованию b'Hello' вместо b'\x48\x65\x6c\x6c\x6f' могла быть связана с тем, что многие популярные протоколы такие как HTTP свободно смешивают текст (закодированный в ascii-совместимой кодировке) и двоичные данные. Поэтому использование символов вместо hex-кодов может помочь при отладке. Недостаток использования b'Hello' вместо b'\x48\x65\x6c\x6c\x6f' состоит в том что люди смешивают понятия текста (Юникодные строки) и двоичных данных (байтов), что ведёт к путанице и в итоге мусору (кракозябрам) в результатах. Что было особенно остро на Питоне 2, где str = bytes. See Stop displaying elements of bytes objects as printable ASCII characters in CPython 3 [python-ideas mailing list (2014)]. Без явного указания кодировки, последовательность байтов (bytes объект) является просто набором чисел. Последовательность байтов становится текстом только, если байты декодированы, используя подходящую кодировку: unicode_text = bytestring.decode(character_encoding)

Ответ 2



Попробуйте это. Функция ord вернет значение символа в десятеричном коде: text = "Hello world!" [(c, ord(c), hex(ord(c))) for c in text] Результат: [('H', 72, '0x48'), ('e', 101, '0x65'), ('l', 108, '0x6c'), ('l', 108, '0x6c'), ('o', 111, '0x6f'), (' ', 32, '0x20'), ('w', 119, '0x77'), ('o', 111, '0x6f'), ('r', 114, '0x72'), ('l', 108, '0x6c'), ('d', 100, '0x64'), ('!', 33, '0x21')]

пятница, 13 декабря 2019 г.

Кодирование текста в произвольный двоичный код и обратно. Пример: “А” <-> “01100011”

#python #алгоритм #python_3x #encoding #byte


Мне нужно преобразовать строку, например "А", в строку двоичного кода, например "01100011",
потом обработать немного двоичный код, пропустив его по функции "Исключающее ИЛИ" с
другим двоичным кодом, например "01100011" с "11000010", тогда выйдет "10100001", и
обратно перевести получившийся код в читаемую строку, например в "Т". 

При этом, я хочу использовать русскую, английскую и украинскую раскладку и цифры,
со знаками припинания. Не подскажете, как это сделать на Python 3?

Вопрос состоит в том как в Python преобразовать строку в двоичный код и обратно используя
любой алгоритм кодировки? 
    


Ответы

Ответ 1



Чтобы произвольный текст превратить в "01"-строки (биты): def text_to_bits(text, encoding='utf-8', errors='surrogatepass'): bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:] return bits.zfill(8 * ((len(bits) + 7) // 8)) И обратно: def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'): n = int(bits, 2) return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0' Пример: >>> text_to_bits("мiр"))) '1101000010111100011010011101000110000000' >>> text_from_bits(_) мiр См. Convert binary to ASCII and vice versa. Чтобы выполнить XOR над двумя строками, нет необходимости биты в виде ascii-строк выражать: from itertools import cycle def xor(message, key): return bytes(a^b for a, b in zip(message, cycle(key))) Достаточно текст в байты закодировать, используя .encode() метод: >>> key = b'key' >>> xor('hello world'.encode(), key) b'\x03\x00\x15\x07\nY\x1c\n\x0b\x07\x01' >>> xor(_, key).decode() # и обратно 'hello world' См. Перевести с PHP на python: XOR с ключём для строки. Для больших строк, можно numpy использовать: import numpy as np # pip install numpy def slow_xor(aa, bb): a = np.frombuffer(aa, dtype=np.byte) b = np.frombuffer(bb, dtype=np.byte) return np.bitwise_xor(a, b).tostring() Пример: >>> slow_xor(b'hello...', 'миръ'.encode()) b'\xb8\xd9\xbc\xd4\xbe\xae\xff\xa4' Если вы хотите ускорить эту функцию, см. Simple Python Challenge: Fastest Bitwise XOR on Data Buffers.

Ответ 2



Решение поддерживающее Unicode Basic Multilingual Plane (BMP) AKA Plane Unicode символы: s = 'отака собі тестова - String !' def encode(s): return list(map(lambda x: "{0:b}".format(ord(x)).zfill(16), s)) def decode(lst): return ''.join(map(lambda x: chr(int(x,2)), lst)) Тест: In [10]: lst = encode(s) In [11]: lst Out[11]: ['0000010000111110', '0000010001000010', '0000010000110000', '0000010000111010', '0000010000110000', '0000000000100000', '0000010001000001', '0000010000111110', '0000010000110001', '0000010001010110', '0000000000100000', '0000010001000010', '0000010000110101', '0000010001000001', '0000010001000010', '0000010000111110', '0000010000110010', '0000010000110000', '0000000000100000', '0000000000101101', '0000000000100000', '0000000001010011', '0000000001110100', '0000000001110010', '0000000001101001', '0000000001101110', '0000000001100111', '0000000000100000', '0000000000100001'] In [12]: decode(lst) Out[12]: 'отака собі тестова - String !'

суббота, 6 июля 2019 г.

Длинные идентификаторы пользователей VK

Еще давно я наблюдал во ВКонтакте длинные идентификаторы пользователей, например: Ссылка vk.com/id1 будет эквивалентом vk.com/id4294967297.
Я разобрался лишь в том, что это число 4294967296 это 2^32 степени, еще тот факт, что если брать 2^32 (к примеру) и прибавить к нему свой идентификатор страницы, то мы получаем тот самый длинный ID.
PS. Проверял так же 2^33 и выше по такому же принципу, все так же получается длинные идентификаторы.
Вопрос: откуда берутся такие числа? И как их можно получить не ручным перебором?


Ответ

Требуется найти числа, которые по модулю 2^32 равны заданному ID.
В общем виде это выглядят так:
ID + (k * 2^32)
Подробнее:
k - неотрицательное целое число (0, 1, 2, 3, ...) ID - идентификатор пользователя VK

вторник, 18 июня 2019 г.

Вывод массива байтов в терминале COM порта

Здравствуйте,
пишу программу на си. Хочу по uart передать следующую последовательность байтов: "0x1F 0x10 0x00 0x01 0x00 0x01" . Т.к. типа byte в си нет, использую char.
Программа выглядит примерно следующим образом:
char str[6]= {31, 16, 0, 1, 0, 1 };
printf("%s
", str);
Проблема в том что эту последовательность я вывожу на терминал последовательного порта и он выводит только 0x1F 0x10, потому что '0' является символом конца строки, поэтому он думает что строка заканчивается и обрезает остальную часть.
Подскажите пожалуйста можно ли вывести на терминал всю строку с нулем вместе, т.е. чтобы ноль не являлся концом строки ?
Использую терминал termite.
Спасибо всем за ответы.
Проблема решена с использованием не массива символов типа char а массива с типом uint8_t (аналог byte в си), которая находиться в библиотеке stdint.h . Код программы:
#include
uint8_t str[6] = {0x1F, 0x10, 0x00, 0x01, 0x00, 0x01}; fwrite(str,sizeof(str),1,stdout);
Спасибо большое, gbg, за помощь.


Ответ

Первое. Тип байтов в C есть и называется uint8_t. Живет в stdint.h
Второе. Используйте fwrite(str,sizeof(str),1,stdout);

понедельник, 10 июня 2019 г.

utf-8' codec can't decode byte 0x89 in position 0: invalid start byte при открытии фото

Имеется Django модель user.path, в которой лежит название фото в формате
"{:%Y-%m-%d %H-%M-%S}.png".format(datetime.now())
Тоесть вот такого вида 2018-01-19 12-17-07.png
Пытаюсь отправить ее пользователю
ppath = 'путь к директории с фото' photo = open(ppath + urllib.parse.unquote_plus(user.path))
Но в итоге получаю ошибку
utf-8' codec can't decode byte 0x89 in position 0: invalid start byte


Ответ

Почему open(..., 'rb') помогло?
Дело в том, что без по умолчанию open открывает файлы в режим чтения r. Этот режим включает в себя чтение массива байтов и приведение его к строке, используя указанную кодировку (или системную кодировку, если не указывать).
Файлы фотографий (картинок) являются бинарными файлами, поэтому попытка получения из них текста в указанной кодировке, скорее всего, вызовет ошибку:
ppath = 'путь к директории с фото' photo = open(ppath + urllib.parse.unquote_plus(user.path))
Поэтому, открытие файла в бинарном режиме и помогло:
ppath = 'путь к директории с фото' file_name = ppath + urllib.parse.unquote_plus(user.path) photo = open(file_name, 'rb')

суббота, 1 июня 2019 г.

Байты - перевод из строки

data = "Hello".encode("utf-8") # перевод в байты
не могу разобраться в байтах... как бы я не старался, Python мне выдает b'Hello'... как мне получить исходные байты этой строки?
Если попробовать с кириллицей, то все получается:
data = "Привет".encode("utf-8") # b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'
или я не имею представления о байтах? объясните пожалуйста


Ответ

Как b'Hello' так и b'\xd0\x9f\xd1\x80...' принадлежат к одному типу bytes
b'Hello' == b'\x48\x65\x6c\x6c\x6f'. Байты, которые соответствуют печатаемым ascii символам (0x20..0x7e), по умолчанию показаны как эти символы в текстовом представлении repr(data) -- синтаксис, используемый для bytes-конcтант в исходном коде Питона (eval(repr(data)) == data).
Использование символов для некоторых байтов вместо шестнадцатеричных кодов может вводить в заблуждение (как в этом случае). Легко получить hexdump, если необходимо
>>> b'Hello'.hex() '48656c6c6f'
Мотивация по использованию b'Hello' вместо b'\x48\x65\x6c\x6c\x6f' могла быть связана с тем, что многие популярные протоколы такие как HTTP свободно смешивают текст (закодированный в ascii-совместимой кодировке) и двоичные данные. Поэтому использование символов вместо hex-кодов может помочь при отладке.
Недостаток использования b'Hello' вместо b'\x48\x65\x6c\x6c\x6f' состоит в том что люди смешивают понятия текста (Юникодные строки) и двоичных данных (байтов), что ведёт к путанице и в итоге мусору (кракозябрам) в результатах. Что было особенно остро на Питоне 2, где str = bytes. See Stop displaying elements of bytes objects as printable ASCII characters in CPython 3 [python-ideas mailing list (2014)]
Без явного указания кодировки, последовательность байтов (bytes объект) является просто набором чисел. Последовательность байтов становится текстом только, если байты декодированы, используя подходящую кодировку:
unicode_text = bytestring.decode(character_encoding)

понедельник, 1 апреля 2019 г.

Как привести массив byte[] к виду CharSequence?

Нужно написать класс AsciiCharSequence, который реализует хранение последовательности ASCII-символов в массиве байт. По сравнению с классом String, хранящим каждый символ как char, AsciiCharSequence будет занимать меньше памяти.
Класс AsciiCharSequence должен:
реализовывать интерфейс java.lang.CharSequence иметь конструктор, принимающий массив байт; определять методы length(), charAt(), subSequence() и toString()
Ну вот я почти написал:
public class AsciiCharSequence implements CharSequence {
byte[] a1;
public AsciiCharSequence(byte[] a){ //Конструктор класса a = this.a1; }
@Override public String toString() { //Переопределение toString() return "AsciiCharSequence{" + "a1=" + Arrays.toString(a1) + '}'; }
@Override public int length(){ return a1.length; }; //Переопределение length()
@Override public char charAt(int index){ //Переопределение charAt() char t000 = (char)a1[index]; return t000; }
@Override public CharSequence subSequence(int start, int end){ //Переопределение subSequence() CharSequence buf[] = new CharSequence[end - start];
for(int i=start; i<=end;i++) { byte t = a1[i-start]; buf[i]=(CharSequence)t; } return buf[end -start]; } }
Самый проблемный участок = Переопределение subSequence(). Это последние 12 строчек с конца. Проблема такая: я никак не могу написать код, чтобы метод возвращал корректный тип (CharSequence?). Если алгоритм формирования массива более-менее понятен, то преобразование массива byte[] в CharSequence совсем не ясен. Сам метод должен применяться на массив символов и возвращать массив символов с индексами лежащими от start до end. К примеру,
String s0 = "Вова и Дима козлы"; s0.subSequence(14,16)
Должен возвращать "злы".


Ответ

Можно переписать класс в таком виде:
public class AsciiCharSequence implements CharSequence { private byte[] data;
public AsciiCharSequence(byte[] data) { this.data = data; }
@Override public int length() { return data.length; }
@Override public char charAt(int index) { return (char) (data[index] & 0xff); }
@Override public CharSequence subSequence(int start, int end) { int length = end - start; byte[] bytes = new byte[length]; for (int i = 0, j = start; i < length; i++, j++) { bytes[i] = data[j]; } return new AsciiCharSequence(bytes); }
@Override public String toString() { return new String(data); } }
Дернуто с гитхаба. Автор - Михаил Валейко.

среда, 12 декабря 2018 г.

Кодирование текста в произвольный двоичный код и обратно. Пример: “А” <-> “01100011”

Мне нужно преобразовать строку, например "А", в строку двоичного кода, например "01100011", потом обработать немного двоичный код, пропустив его по функции "Исключающее ИЛИ" с другим двоичным кодом, например "01100011" с "11000010", тогда выйдет "10100001", и обратно перевести получившийся код в читаемую строку, например в "Т".
При этом, я хочу использовать русскую, английскую и украинскую раскладку и цифры, со знаками припинания. Не подскажете, как это сделать на Python 3?
Вопрос состоит в том как в Python преобразовать строку в двоичный код и обратно используя любой алгоритм кодировки?


Ответ

Чтобы произвольный текст превратить в "01"-строки (биты):
def text_to_bits(text, encoding='utf-8', errors='surrogatepass'): bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:] return bits.zfill(8 * ((len(bits) + 7) // 8))
И обратно:
def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'): n = int(bits, 2) return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
Пример:
>>> text_to_bits("мiр"))) '1101000010111100011010011101000110000000' >>> text_from_bits(_) мiр
См. Convert binary to ASCII and vice versa

Чтобы выполнить XOR над двумя строками, нет необходимости биты в виде ascii-строк выражать:
from itertools import cycle
def xor(message, key): return bytes(a^b for a, b in zip(message, cycle(key)))
Достаточно текст в байты закодировать, используя .encode() метод:
>>> key = b'key' >>> xor('hello world'.encode(), key) b'\x03\x00\x15\x07
Y\x1c
\x0b\x07\x01' >>> xor(_, key).decode() # и обратно 'hello world'
См. Перевести с PHP на python: XOR с ключём для строки
Для больших строк, можно numpy использовать:
import numpy as np # pip install numpy
def slow_xor(aa, bb): a = np.frombuffer(aa, dtype=np.byte) b = np.frombuffer(bb, dtype=np.byte) return np.bitwise_xor(a, b).tostring()
Пример:
>>> slow_xor(b'hello...', 'миръ'.encode()) b'\xb8\xd9\xbc\xd4\xbe\xae\xff\xa4'
Если вы хотите ускорить эту функцию, см. Simple Python Challenge: Fastest Bitwise XOR on Data Buffers

понедельник, 26 ноября 2018 г.

Перевод числа в массив байтов

Как представить число (int, float) в виде массива байтов в Java?


Ответ

Для этого можно воспользоваться ByteBuffer-ом:
int value = 100000; byte[] bytes = ByteBuffer.allocate(4).putInt(value).array();
и
float floatValue = 100.5f; byte[] floatBytes = ByteBuffer.allocate(4).putFloat(floatValue).array();