Проблема читання бінарного файлу

💡 Усі статті, обговорення, новини про Java — в одному місці. Приєднуйтесь до Java спільноти!

DataOutputStream

Доброго дня. виникла невеличка проблема:

суть запитання: є вихідний масив цілих чисел типу int. виглядає, приблизно осьтак:

1 0 1 1 1 0 1 0 1 3456 1 0 0 0 0 
2 0 1 1 1 0 2 0 2 23336 23253712 2 0 0 0 0 
3 0 1 1 1 0 3 -1 2 2346433 52111123 3 0 0 0 0 
4 0 1 1 2 0 4 0 1234 2 591812489 159580160 4 0 0 0 0 
5 0 1 1 2 0 5 -1 23465 2 -1739291791 0 5 0 0 0 0 

записаний він у бінарний файл за допомогою Java, а конкретно класу DataOtputStream та його методу writeInt(). файл потрібно считати за допомогою с++, однак при читанні файлу виходить щось не зрозуміле:

результат читання плюсами:

16777216 0 16777216 16777216 16777216 0 16777216 0 16777216 −2146631680 16777216 0 0 0 0 33554432 0 16777216 16777216 16777216 0 33554432 0 33554432 677052416 −791518719 33554432 0 0 0 0 ....

функція читання файлу:

void readCode(string path) {
    ifstream file(path, ios::binary);
    if (!file.is_open()) {
        cerr << "Error opening file" << endl;
    }
    file.seekg(0, ios::end);
    streamsize syze = file.tellg();
    file.seekg(0, ios::beg);
    size_t count = syze / sizeof(int);
    vector<int> code (count);
    if(file.read(reinterpret_cast<char*>(code.data()), syze)) {
    };
        file.close();
    for (int i : code) {
        cout << i << " ";
    }
}
int main() {
    readCode("/home/as/IdeaProjects/Colibri/res/test.cof");
    return 0;
}

можливо, хтось знає в чому проблема та як її можна вирішити? Дякую.

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Ви перемудрили тут із С++, читати треба не весь вектор одразу, а одну окрему перемінну взявши її адрес стеку через & і привівши вказівник із const int* до char* (так io stream жахливий API для бінарної роботи, карще будо спитати ШІ згенерувати код на базі С API), і робити це в циклі до вашого count, потім додавати значення в вектор через code.push_back(i)
Подивіться в прикладі як читають double перемінну en.cppreference.com/...​o/basic_istream/read.html
2. Враховуючи що існує порядок слідування байтів big end endian та little endian ваша ідея так користуватись файлом, така собі. Працює добре тільки якщо ви впевнені, що не буде передачі по сіті і один і той же порядок слідування байтів на всіх системах де буде використовуватись файл (у більшості сучасних процессорів little endian, android включає на Arm саме LiEndian, але скажімо Power PC — BiEndian це дуже старі маки чи старі Sony Play Station 3 і т.п. ).
Краще скористуйтесь Google protocol buffers або ASN1 форматом. І відповідними генераторами чи бібліотеками.

реализация сериализации и десериализации отличается. либо используй 3rd party кроссплатформенную, либо возьми одну из тех что у тебя есть, а вторую сторону перепиши под нее

ах блин.... это старье кто-то апнул....

Скинь питання в чат гпт і попроси пофіксати

hexdump погуглиш? Подивись, в якому вигляді writeInt() пише числа в файл :)

Але тут і без нього видно, що 0×00000001 перетворюється на 0×00010000 :-D

Почитай, що таке Big Endian і Little Endian.

set дотошний_зануда_мод=on

перетворюється на

0×01000000

Читати, першим ділом, слід було власне Джавішну документацію
docs.oracle.com/...​Stream.html#writeInt-int
“Writes an int to the underlying output stream as four bytes, high byte first...”

а тоді вже про Big Endian і Little Endian та розмір int на платформі (й юзати int32_t відповідно)

Ну, сорян, я джаву 1 раз в житті бачив: наклепав якось якийсь мерчант гейтвей на замовлення — це весь досвід :-D

Це тому що файл бінарний, по сьогоднішнім реаліям мав би бути небінарний.

тому що файл бінарний ... мав би бути небінарний

проблем можна і текстом знайти

по сьогоднішнім реаліям

шінарний)

а вы говорите вайбкодинг ))

найбільш ймовірно дата (big-endian) зчитувались на x86 (little-endian), у цьому випадку там де дата читаються — поміняйте порядок байт в native для архітектури хоста (нп з ntohl())

додатково на потім ще — якщо java гарантує що int то int32_t, то і зчитувати у int32_t щоб розміри однакові були

p.s. endian(3), intN_t(3type)

Я вибачаюсь за питання, але,
Кто вам взагалі С++ в руки дав ?

Я вибачаюсь за відповідь: дайте вам в руки невідомий для вас інструмент, і скажіть — зроби! ви зразу такий а}{...ниий форсюзер, пишете код на льоту, у вас все виходить з першого разу, а що не виходить ви затикаєте порадами з чату ЖПТ, не розуміючи суті, як воно має працювати? так?

Просто порядок байт та розміщення данних в пам,яті нам в унівєрі розказували, ще на самому початку.
Поки нам то в голову не втулмачили ніякі С, С++, Паскалі нам не давали вивчати (1999 рік) бо то основа основ і воно не залежить від конкретної МП.

Ваш файл текстовий, треба читати як текст з розбиттям на «слова» по пробілам, далі кожне «слово» перевести в тип int. Бінарний то трохи інше))) джава має специфічне уявлення про типи і гонить все в рядок тексту.

Тебе чатжпт забанив?

а звідки я по вашому взяла методику считки бінарніка на плюсах? на рідній Жабці проблем немає, але завдання стоїть зробити цю байду в плюсах. Через DataInputStream, в Java читається коректно, а от з плюсами проблема ;(. в мене вже виникає підозра що в яві і в плюсах різна довжина інтів...

.gitattributes prevent from doing stuff like changing line endings.

Ні, проблема не в плюсах, а в непрофесійності того, хто С++ намагається використати, не маючи уявлення зеленого про фундаментальні речі із Computer Science.

я взагалі з плюсами працюю лише четвертий день, тож, сорян, що ставлю вам, крутим гуру, такі тупі запитання

Плюси тут не до чого, це з загального розуміння що як працює. Враховуючи java, то питання до речі також нормальне (якщо не ціль залишатися в рамках-лімітах одніє-двох мп, до речі кодери зазвичай звертають увагу тільки на якість чи чистоту самого коду часто залишаючи суть поза увагою).

Я тому й наголосив, що знання C++ тут ні до чого.

що знання C++ тут ні до чого.

а знайшов де то було карочі там тема цікава там на справді «знання сі++» виявляються такими суто абстрактними як то «абстрактний сі++» без будь якого розуміння що там під ним чи що там він значить якісь ті чи інші абстракції

це більше схоже імхо на старий добрий фортран чим навіть на джаву якусь

ЗЫ: навіяло відповісти сюди щойно «закритою» темою за спілкування з педофілами за інтерфейс spdif на тему «чи звучить різний кабель spdif залежно від якості і пєдофільності» ... то там як то фішки на кшталт

не слід забувати що разом з корисним сигналом через spdif кабель з одного дівайсу на інший пролазять також шкідливі шуми та перешкоди різноманітного спектру

на чому я «дискусію» закрив і згадав оце ще за сі++ «знання» ))

ЗЫ: можу накинуть практичного прикладу

люди сірьозно вважають що то і єто єто другоє

class B { ... }
class C : public B { ... }

B* pb = new C{};
...
C c{};
B* pb = &c;

і що № 2 куди тільки не показує но зазвичай конєшно на B

що знання C++ тут ні до чого.

; після боді класу тре ставити.
pb зміну 2 рази деклруєш.
Ну і якщо 2й раз ти просто присвоюєш нове значення, то кто попередній вказівник видаляти буде.

gemini

Доброго дня! Ви зіткнулися з класичною проблемою при передачі бінарних даних між різними платформами або мовами програмування — порядком байтів (Endianness).У чому причина?Java (DataOutputStream): Цей клас використовує стандарт Big-Endian. Це означає, що старший байт числа записується першим. C++ (на більшості сучасних ПК): Процесори Intel та AMD використовують архітектуру x86, яка працює за стандартом Little-Endian. Тут першим записується молодший байт.Коли ви записуєте число 1 у Java (writeInt), воно в пам’яті виглядає як 00 00 00 01.Коли C++ читає ці 4 байти на Little-Endian системі, він інтерпретує їх «задом наперед», і число 01 00 00 00 перетворюється на $2^{24}$ або 16,777,216. Саме цей результат ви і бачите у своєму виводі.Як це виправити у C++? Вам потрібно змінити порядок байтів (swap bytes) після зчитування кожного числа. Ось як це можна зробити:

...

Зауважте, що пояснення було отримане за допомогою ШІ. Можете піти за посиланням: Промпт безпосередньо був взятий з стартового повідомлення. В майбутньому не соромтесь вживати ШІ в праці.

Підписатись на коментарі