Страницы

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

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

понедельник, 30 марта 2020 г.

Вывод XML на консоль - отсутствует заголовок xml файла C#

#c_sharp #xml #binary


Создал XML файл с помощью класса  XDocument. Вывожу готовую Xml в Консоль, но не
вижу там xml заголовка в начале файла. Если его сохранить на диск, то заголовок присутствует.
Почему так происходит? И как можно его туда добавить?

XDocument xdoc = new XDocument(

        new XDeclaration("1.0", "Windows-1251","yes"),
        new XElement("Product",
            new XElement ("prequest",
            new XElement("req",
            new XElement("AddressReq",
                new XElement ("street","Горького"),
                new XElement ("houseNumber","1"),
                new XElement("apartment", "38"),
                new XElement("city", "Магадан"),
                new XElement("postal", "685000"),
                new XElement("addressType", "1")),
            new XElement("AddressReq",
                new XElement("street", "Горького"),
                new XElement("houseNumber", "1"),
                new XElement("apartment", "38"),
                new XElement("city", "Магадан"),
                new XElement("postal", "685000"),
                new XElement("addressType", "1")),
            new XElement("IdReq",
                new XElement("idNum", "273"),
                new XElement("idType","21"),
                new XElement("seriesNumber", "64"),
                new XElement("issueCountry", "г. Магадан"),
                new XElement("issueDate", "2006-03-18"),
                new XElement("issueAuthority", "ОВД")
            ),
            new XElement("IdReq",
                new XElement("idNum", "1"),
                new XElement("idType", "32")
            ),
            new XElement("InquiryReq",
                new XElement("ConsentReq",
                 new XElement("consentFlag", "Y"),
                 new XElement("consentDate", "2016-01-20"),
                 new XElement("consentExpireDate", "2021-10-21"),
                 new XElement("consentPurpose", "4"),
                 new XElement("otherConsentPurpose", "Job pre-screening"),
                 new XElement("reportUser", "DG Human Resources Incorporated"),
                 new XElement("liability", "Y")
                ),
                 new XElement("inqPurpose", "01"),
                 new XElement("inqAmount", "10000"),
                 new XElement("currencyCode", "usd")
            ),
             new XElement("PersonReq",
                new XElement("name1", "К"),
                new XElement("first", "Г"),
                new XElement("paternal", "Г"),
                new XElement("gender", "1"),
                new XElement("birthDt", "1900-00-00"),
                new XElement("placeOfBirth", "Москва")
            ),
             new XElement("RequestorReq",
                new XElement("MemberCode", "V"),
                new XElement("UserID", "V"),
                new XElement("Password", "1")
            ),
             new XElement("RefReq",

                new XElement("product", "CHST")
            ),
             new XElement("IOType","B2B"),
             new XElement("OutputFormat", "xml"),
             new XElement("lang", "ru")
            ))               
            ))


Вывод в консоль :

xdoc.Save("C:\\file.xml");  //В сохраненном файле xml есть заголовок
        byte[] byteArray = Encoding.GetEncoding(1251).GetBytes(xdoc.ToString());
        BinaryWriter write = new BinaryWriter(File.Open("C:\\file.dat", FileMode.OpenOrCreate));
        write.Write(byteArray); //а вот в бинарном файле нет.

        Console.WriteLine(xdoc); //Если вывести сам xdoc то тут тоже нет заголовка.
         
        Console.ReadKey();

    


Ответы

Ответ 1



Метод ToString у класса XDocument не выводит заголовок xml. Поэтому его нет в бинарном файле. Когда вы пишете Console.WriteLine(xdoc) - тут тоже вызывается ToString. Хотите получить заголовок в консоли, используйте xdoc.Save(Console.Out); Не пугайтесь, что encoding выведется другой. Кодировка будет такой, какую поддерживает консоль.

Ответ 2



Как верно заметили в соседнем ответе, XDocument.ToString() не отображает декларацию документа, но ее можно вывести отдельно: Console.WriteLine(xdoc.Declaration); Console.WriteLine(xdoc);

вторник, 17 марта 2020 г.

Неверное получение байтов на javaScript

#binary #javascript


На C# через BinaryWriter запаковываю int'овые значения в бинарный файл.
Этот шаг выполняется отлично, но проблема в следующем:
При загрузке этих данных через JavaScript я получаю строку через XMLHttpRequest,
далее, для наглядности, формирую массив, элементы которого состоят из 4 байтов.
var dat=http.responseText;

                var bytes = [];
                for (var i = 0; i < dat.length; i+=4)
                {   var arr='';

                    for(var l=3;l>=0;l--)
                    {
                        for(var j=7;j>=0;j--)
                        arr+=dat.charCodeAt(i+3-l)>>j & 1;
                    arr+=" ";
                    }

                    bytes.push(arr);

                }

                console.log(bytes);

В результате получаются искаженные данные, например,  первые 4 байта в файле выглядят
так в двоичном коде:
00011000 01100111 00000011 00000000
а javaScript получает их как

11111101 00001000 00000010 00000000
В чем причина?

Дополнительные исследования:
При записи в файлы поменял кодировку на Unicode, не знаю, как это объяснить, но теперь
байты считываются правильно, кроме тех, у которых в старшем бите 1, тогда те полностью
преобразовываются в 11111101.    


Ответы

Ответ 1



Смотрели Sending and Receiving Binary Data? Не responseText, а response. var byteArray = new Uint8Array(dat);. Я не исследовал вопрос бинарных данных в JS пока, только собираюсь заняться, поэтому не ответ, а лишь догадки.

воскресенье, 15 марта 2020 г.

Как сравнить несколько бит данных?

#c #binary


Имеется байт данных, в bin: 11010000, как можно проверить что первые 3 бита - 110?
    


Ответы

Ответ 1



Один из многих путей: (bin >> 5) & 7 == 6 Что происходит: Сдвигаем нужные биты влево xxxxxxxx11010000 // было xxxxxxxxxxxxx110 // стало Применяем маску, которая вытащит только нужные биты: xxxxxxxxxxxxx110 // было 111 // маска 0000000000000110 // стало Результат сравниваем с нужной комбинацией бит (бинарное 110 — это 6). Обычно вам не должно хотеться сравнивать биты вручную, это слишком низкоуровневая операция. Для таких штук часто лучше приспособлены битовые поля: struct Data { unsigned int p1 : 3; // первые три бита unsigned int p2 : 1; // следующий 1 бит unsigned int p3 : 4; // следующие 4 бита }; Data data; // ... if (data.p1 == 6) { Здесь все сдвиги сделает за вас компилятор.

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

Деление с остатком uint64_t на 10

#c #алгоритм #binary


На 32-bit микропроцессоре нужна функция (эффективный алгоритм) для получения частного
и остатка от деления uint64_t на 10 (как всегда для печати).

Полазив по интернету, в http://www.hackersdelight.org/divcMore.pdf нашел лишь нечто
похожее (для uint32_t) с вот таким кодом

unsigned divu10(unsigned n) {
    unsigned q, r;
    q = (n >> 1) + (n >> 2);
    q = q + (q >> 4);
    q = q + (q >> 8);
    q = q + (q >> 16);
    q = q >> 3;
    r = n - q*10;
    return q + ((r + 6) >> 4);
    // return q + (r > 9);
}


Для своей цели изменил ее вот так (фактически, добавил оператор q = q + (q >> 32); :

uint64_t divu64_10 (uint64_t n, uint32_t *rem) {
  uint64_t q, r;
  q = (n >> 1) + (n >> 2);
  q = q + (q >> 4);
  q = q + (q >> 8);
  q = q + (q >> 16);
  q = q + (q >> 32);
  q = q >> 3;
  r = n - ((q << 3) + (q << 1));
  *rem = r > 9 ? r - 10 : r;

  //  orig: return q + ((r + 6) >> 4);
  return q + (r > 9);
}


Проверил, вводя разные числа вот в таком коде на нормальном 64-бит компе:

  unsigned long long v;

  while (scanf("%llu", &v) == 1) {
    unsigned long long d;
    uint32_t r;

    d = divu64_10(v, &r);
    printf("divu10: %llu %u (C: %llu %llu)\n",
       d, r,
       v / 10, v % 10);
  }


Похоже, мое изменение работает.

Вопрос, собственно в следующем -- может ли кто-нибудь в самом деле разбирающийся
в двоичной арифметике подтвердить, что divu64_10() работает верно?
    


Ответы

Ответ 1



Разберем как работает исходный код. Он вычисляет q = n * 0x33333333 >> 33, что примерно равно n * 0.0999999999.... Затем вычисляет ошибку n - q*10, и если она меньше 10, то всё правильно, если больше 10, то к результату добавляется 1. Расмотрим значения ошибок. 10 * 0x33333333 / 2 ** 33 = 0b00.111111111111111111111111111111110 11 * 0x33333333 / 2 ** 33 = 0b01.000110011001100110011001100110001 19 * 0x33333333 / 2 ** 33 = 0b01.111001100110011001100110011001001 20 * 0x33333333 / 2 ** 33 = 0b01.111111111111111111111111111111100 21 * 0x33333333 / 2 ** 33 = 0b10.000110011001100110011001100101111 ... 65530 * 0x33333333 / 2 ** 33 = 6552.999998474261 = 0b1100110011000.111111111111111111100110011001110 ... 4294967290 * 0x33333333 / 2 ** 33 = 429496728.9 = 0b11001100110011001100110011000.111001100110011001100110011001110 Видно что для n = 10*d + r, ошибка равна 10 если r=0. Можно посчитать, что если бы вместо сдвига было бы деление, то ошибка была бы равна n - n * 10 * 0x33333333 / 2**33 = n / 2 ** 32 Так как n < 2 ** 32, то ошибка результата не превышает единицу. Для 64 разрядов всё так же, только считаем n * 0x3333333333333333 >> 65. Добавление q += q >> 32 эквивалентно умножению на (2**32+1)/2**32, при этом (2**32+1)*0x33333333 = 0x3333333333333333.

среда, 17 июля 2019 г.

Как записать двумерный вектор в двоичный файл?

Предположим, что у меня имеется какой-то двумерный вектор:
std::vector> main_vector; std::vector temp_vector;
for (std::size_t i = 0; i < 5; i++) temp_vector.push_back(i); for (std::size_t i = 0; i < 5; i++) main_vector.push_back(temp_vector);
Как записать его в двоичный файл? Соответственно, размерность неизвестна. Знаю, что стандартным образом как с массивами не прокатит.
bin_file.open("test.txt", std::ios::out | std::ios::binary); bin_file.write((char *)&main_vector, sizeof(main_vector)); //не сработает


Ответ

Решение вот (проверено):
std::ofstream bin_file; std::vector> main_vector; main_vector.resize(5);
const int n = 5; const int m = 5; for (std::size_t i = 0; n < 5; i++) { for (std::size_t j = 0; m < 5; j++) { main_vector[i].push_back(j); } } //демонстрация в поток вывода элементов нашего вектора for (int i {}; i < n; ++i) { for (int j {}; j < m; ++j) { std::cout << main_vector[i][j] << ' '; } } std::cout << std::endl; //запись в файл (расширение УКАЗАННО ВОПРОШАЮЩИМ!) bin_file.open("test.txt", std::ios::out | std::ios::binary); for (int i{}; i < main_vector.size(); ++i) { bin_file.write((char *)&main_vector[i][0], main_vector[i].size() * sizeof(main_vector[i][0])); } bin_file.close();
Ну а проверить что у вас вывелось в файл можно следующим образом:
char array[n * m * sizeof(main_vector[0][0])];
read_file.open("test.txt", std::ios::in | std::ios::binary); read_file.read(array, sizeof(array)); read_file.close();
int *arr = reinterpret_cast(array); for (int i {}; i < n * m; ++i) { std::cout << *arr << ' '; ++arr; }
return 0; }

пятница, 7 июня 2019 г.

Вывод XML на консоль - отсутствует заголовок xml файла C#

Создал XML файл с помощью класса XDocument. Вывожу готовую Xml в Консоль, но не вижу там xml заголовка в начале файла. Если его сохранить на диск, то заголовок присутствует. Почему так происходит? И как можно его туда добавить?
XDocument xdoc = new XDocument(
new XDeclaration("1.0", "Windows-1251","yes"), new XElement("Product", new XElement ("prequest", new XElement("req", new XElement("AddressReq", new XElement ("street","Горького"), new XElement ("houseNumber","1"), new XElement("apartment", "38"), new XElement("city", "Магадан"), new XElement("postal", "685000"), new XElement("addressType", "1")), new XElement("AddressReq", new XElement("street", "Горького"), new XElement("houseNumber", "1"), new XElement("apartment", "38"), new XElement("city", "Магадан"), new XElement("postal", "685000"), new XElement("addressType", "1")), new XElement("IdReq", new XElement("idNum", "273"), new XElement("idType","21"), new XElement("seriesNumber", "64"), new XElement("issueCountry", "г. Магадан"), new XElement("issueDate", "2006-03-18"), new XElement("issueAuthority", "ОВД") ), new XElement("IdReq", new XElement("idNum", "1"), new XElement("idType", "32") ), new XElement("InquiryReq", new XElement("ConsentReq", new XElement("consentFlag", "Y"), new XElement("consentDate", "2016-01-20"), new XElement("consentExpireDate", "2021-10-21"), new XElement("consentPurpose", "4"), new XElement("otherConsentPurpose", "Job pre-screening"), new XElement("reportUser", "DG Human Resources Incorporated"), new XElement("liability", "Y") ), new XElement("inqPurpose", "01"), new XElement("inqAmount", "10000"), new XElement("currencyCode", "usd") ), new XElement("PersonReq", new XElement("name1", "К"), new XElement("first", "Г"), new XElement("paternal", "Г"), new XElement("gender", "1"), new XElement("birthDt", "1900-00-00"), new XElement("placeOfBirth", "Москва") ), new XElement("RequestorReq", new XElement("MemberCode", "V"), new XElement("UserID", "V"), new XElement("Password", "1") ), new XElement("RefReq",
new XElement("product", "CHST") ), new XElement("IOType","B2B"), new XElement("OutputFormat", "xml"), new XElement("lang", "ru") )) ))
Вывод в консоль :
xdoc.Save("C:\\file.xml"); //В сохраненном файле xml есть заголовок byte[] byteArray = Encoding.GetEncoding(1251).GetBytes(xdoc.ToString()); BinaryWriter write = new BinaryWriter(File.Open("C:\\file.dat", FileMode.OpenOrCreate)); write.Write(byteArray); //а вот в бинарном файле нет.
Console.WriteLine(xdoc); //Если вывести сам xdoc то тут тоже нет заголовка. Console.ReadKey();


Ответ

Метод ToString у класса XDocument не выводит заголовок xml. Поэтому его нет в бинарном файле.
Когда вы пишете Console.WriteLine(xdoc) - тут тоже вызывается ToString
Хотите получить заголовок в консоли, используйте
xdoc.Save(Console.Out);
Не пугайтесь, что encoding выведется другой. Кодировка будет такой, какую поддерживает консоль.

четверг, 6 июня 2019 г.

Неверное получение байтов на javaScript

На C# через BinaryWriter запаковываю int'овые значения в бинарный файл. Этот шаг выполняется отлично, но проблема в следующем: При загрузке этих данных через JavaScript я получаю строку через XMLHttpRequest, далее, для наглядности, формирую массив, элементы которого состоят из 4 байтов. var dat=http.responseText;
var bytes = []; for (var i = 0; i < dat.length; i+=4) { var arr='';
for(var l=3;l>=0;l--) { for(var j=7;j>=0;j--) arr+=dat.charCodeAt(i+3-l)>>j & 1; arr+=" "; }
bytes.push(arr);
}
console.log(bytes); В результате получаются искаженные данные, например, первые 4 байта в файле выглядят так в двоичном коде: 00011000 01100111 00000011 00000000 а javaScript получает их как 11111101 00001000 00000010 00000000 В чем причина? Дополнительные исследования: При записи в файлы поменял кодировку на Unicode, не знаю, как это объяснить, но теперь байты считываются правильно, кроме тех, у которых в старшем бите 1, тогда те полностью преобразовываются в 11111101


Ответ

Смотрели Sending and Receiving Binary Data? Не responseText, а response var byteArray = new Uint8Array(dat); Я не исследовал вопрос бинарных данных в JS пока, только собираюсь заняться, поэтому не ответ, а лишь догадки.

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

Как сравнить несколько бит данных?

Имеется байт данных, в bin: 11010000, как можно проверить что первые 3 бита - 110?


Ответ

Один из многих путей:
(bin >> 5) & 7 == 6
Что происходит:
Сдвигаем нужные биты влево
xxxxxxxx11010000 // было xxxxxxxxxxxxx110 // стало Применяем маску, которая вытащит только нужные биты:
xxxxxxxxxxxxx110 // было 111 // маска 0000000000000110 // стало Результат сравниваем с нужной комбинацией бит (бинарное 110 — это 6).

Обычно вам не должно хотеться сравнивать биты вручную, это слишком низкоуровневая операция. Для таких штук часто лучше приспособлены битовые поля:
struct Data { unsigned int p1 : 3; // первые три бита unsigned int p2 : 1; // следующий 1 бит unsigned int p3 : 4; // следующие 4 бита };
Data data; // ... if (data.p1 == 6) {
Здесь все сдвиги сделает за вас компилятор.

пятница, 26 октября 2018 г.

Деление с остатком uint64_t на 10

На 32-bit микропроцессоре нужна функция (эффективный алгоритм) для получения частного и остатка от деления uint64_t на 10 (как всегда для печати).
Полазив по интернету, в http://www.hackersdelight.org/divcMore.pdf нашел лишь нечто похожее (для uint32_t) с вот таким кодом
unsigned divu10(unsigned n) { unsigned q, r; q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); q = q + (q >> 16); q = q >> 3; r = n - q*10; return q + ((r + 6) >> 4); // return q + (r > 9); }
Для своей цели изменил ее вот так (фактически, добавил оператор q = q + (q >> 32); :
uint64_t divu64_10 (uint64_t n, uint32_t *rem) { uint64_t q, r; q = (n >> 1) + (n >> 2); q = q + (q >> 4); q = q + (q >> 8); q = q + (q >> 16); q = q + (q >> 32); q = q >> 3; r = n - ((q << 3) + (q << 1)); *rem = r > 9 ? r - 10 : r;
// orig: return q + ((r + 6) >> 4); return q + (r > 9); }
Проверил, вводя разные числа вот в таком коде на нормальном 64-бит компе:
unsigned long long v;
while (scanf("%llu", &v) == 1) { unsigned long long d; uint32_t r;
d = divu64_10(v, &r); printf("divu10: %llu %u (C: %llu %llu)
", d, r, v / 10, v % 10); }
Похоже, мое изменение работает.
Вопрос, собственно в следующем -- может ли кто-нибудь в самом деле разбирающийся в двоичной арифметике подтвердить, что divu64_10() работает верно?


Ответ

Разберем как работает исходный код.
Он вычисляет q = n * 0x33333333 >> 33, что примерно равно n * 0.0999999999... Затем вычисляет ошибку n - q*10, и если она меньше 10, то всё правильно, если больше 10, то к результату добавляется 1.
Расмотрим значения ошибок.
10 * 0x33333333 / 2 ** 33 = 0b00.111111111111111111111111111111110 11 * 0x33333333 / 2 ** 33 = 0b01.000110011001100110011001100110001 19 * 0x33333333 / 2 ** 33 = 0b01.111001100110011001100110011001001 20 * 0x33333333 / 2 ** 33 = 0b01.111111111111111111111111111111100 21 * 0x33333333 / 2 ** 33 = 0b10.000110011001100110011001100101111 ... 65530 * 0x33333333 / 2 ** 33 = 6552.999998474261 = 0b1100110011000.111111111111111111100110011001110 ... 4294967290 * 0x33333333 / 2 ** 33 = 429496728.9 = 0b11001100110011001100110011000.111001100110011001100110011001110
Видно что для n = 10*d + r, ошибка равна 10 если r=0.
Можно посчитать, что если бы вместо сдвига было бы деление, то ошибка была бы равна
n - n * 10 * 0x33333333 / 2**33 = n / 2 ** 32
Так как n < 2 ** 32, то ошибка результата не превышает единицу.

Для 64 разрядов всё так же, только считаем n * 0x3333333333333333 >> 65
Добавление q += q >> 32 эквивалентно умножению на (2**32+1)/2**32, при этом (2**32+1)*0x33333333 = 0x3333333333333333