Опитвам се да прочета двоичен файл с низове и цели числа и да отпечатам целите числа, съответстващи на низа

Опитвам се да прочета двоичен файл с низове и цели числа и да отпечатам цялото число, съответстващо на низа, известен още като неговия на същия ред. Знам как да чета цели числа от двоичен файл като read(buffer, 4), но никога преди не съм чел низове. Всъщност нямам представа колко големи са тези низове.. 100 байта четат по-голямата част от файла, но не целия... Форматът на файла изглежда по следния начин.

jcake 567 sgrenon 17

опитвам се да хвана числата след името и да ги отпечатам в iostream. Разбирам как да чета int, защото обикновено има 4 байта. Просто никога не чета двоичен файл с низове в него.

while (readfile.good())
{

    char*buffer = new char[100];
    readfile.read(buffer, 100);
    if (readfile.eof())
    {
        delete[] buffer;
        break;
    }

    cout << buffer << endl;

person Community    schedule 05.02.2017    source източник
comment
Обичайно е да се съхранява дължина за данни с променлива дължина в двоични файлове. Променлива дължина ли е или фиксирана? Имате ли спецификация за формата?   -  person Retired Ninja    schedule 06.02.2017
comment
Не можете да напишете програма за четене на файл, без да имате спецификацията на файловия формат като справка. Имате ли такава спецификация?   -  person Dai    schedule 06.02.2017
comment
Форматът на файла е този jdow 567 /n sgren 7654 име и номер, всяко от тях на собствен ред   -  person    schedule 06.02.2017
comment
Файлът, който описахте, е текстов файл. Какво те кара да мислиш, че е бинарен?   -  person Retired Ninja    schedule 06.02.2017
comment
защото е .dat файл   -  person    schedule 06.02.2017
comment
Разширенията нямат значение, има значение съдържанието на файла.   -  person Retired Ninja    schedule 06.02.2017


Отговори (1)


Има много различни начини за сериализиране на низове в двоични файлове. Най-често срещаните начини са:

  1. Поредица от байтове с префикс на дължина, дължината се съхранява като цяло число и обикновено е с дължина 1, 2 или 4 байта, последвана от самите данни, напр. 0x04 0x46 0x4F 0x4F 0x44 (0x04 = 4 байта, 46,4F,4F,44 == "FOOD"). Тъй като дължината е декларирана, няма нужда от сентинелен маркер, това също позволява използването на нула байтове в низа. 1.1. Понякога се използва цяло число с променлива дължина, но това е усъвършенствана техника.
  2. Използва се стойност на контролен маркер, обикновено знакът NULL '\0', напр. 0x46 0x4F 0x4F 0x44 0x00.
  3. Или файловият формат указва, че низът има фиксирана дължина, в който случай не се изисква нито декларация за дължина в лентата, нито страж, въпреки че понякога спецификация ще каже, че ако действителната дължина на низа е по-малка от фиксираната дължина, тогава null '\0' байта може да се използва като подложка.

Вашият въпрос не се позовава на никаква спецификация, която да подскаже кой формат използвате.

Обърнете внимание, че ако просто искате да прочетете цял файл в паметта, трябва да използвате файл с карта на паметта за по-добра производителност, въпреки че това изисква поддръжка на платформа. Можете да направите това с Boost: http://www.boost.org/doc/libs/1_50_0/libs/iostreams/doc/classes/mapped_file.html

Ако все пак искате да заредите файла в буфер, трябва да разпределите достатъчно голям буфер, за да побере файла, няма да искате да използвате статично разпределен буфер (new char[100], защото е неефективно, ако файлът е по-малък от 100 байта голям и твърде малък, ако е повече от 100 байта.

Ако използвате ifstream, тогава използвайте метода tellg(), за да получите дължината на файла, след което разпределете буфер за него:

using namespace std;

// ...

ifstream in( fileName, ifstream::ate | ifstream::binary );
streamsize length = in.tellg();
if( length <= 0 ) throw ...

size_t bufferLength = static_cast<size_t>( length );
char* buffer = new char[ bufferLength ];

in.read( buffer, bufferLength );

// do stuff with `buffer`

delete[] buffer;
person Dai    schedule 05.02.2017
comment
МНОГО ВИ БЛАГОДАРЯ MCUH!!! Трябваше да знам, че трябва да използвам командата say and seek, за да взема дължината на файла. Оценявам го.. Гласувах за теб, но нямам достатъчно репутация, за да го покажа =*( - person ; 06.02.2017