none
Как работать с *.data файлом ? RRS feed

Ответы

  • В таком случае реализуйте шапку: вы  можете сначала сохранять в файл количество данных, а затем их смещения относительно начала файла, а уж потом сами данные. Например, запись может выглядеть следующим образом:

    FILE* f;
    f=fopen("MyfileOut.dat","w");
    //Пусть количество хранимых данных = 5
    int num1 = 5;
    if(f)
    {	//Возьмем в качестве данных массивы разных размеров
    	int *mas1 = new int[50];
    	for(int i=0; i<50; i++)
    		mas1[i] = 1;
    	int *mas2 = new int[32];
    	for(int i=0; i<32; i++)
    		mas2[i] = 2;
    	int *mas3 = new int[10];
    	for(int i=0; i<10; i++)
    		mas3[i] = 3;
    	int *mas4 = new int[8];
    	for(int i=0; i<8; i++)
    		mas4[i] = 4;
    	int *mas5 = new int[68];
    	for(int i=0; i<68; i++)
    		mas5[i] = 5;
    	//Шапка файла
    	int *offset = new int[6];
    	//Размер шапки 7 INT, т.к. у нас первый INT хранит количество объектов, 
    	//далее будем хранить смещения от начала 5 объектов для сохранения и конец последнего. 
    	//С этой позиции начинаются первые данные.
    	offset[0]= 7*sizeof(int);
    	//С этой позиции начинаются вторые данные
    	offset[1]= offset[0]+50*sizeof(int);
    	//И т.д.
    	offset[2]= offset[1]+32*sizeof(int);
    	offset[3]= offset[2]+10*sizeof(int);
    	offset[4]= offset[3]+8*sizeof(int);
    	//Конец файла на этой позиции
    	offset[5]= offset[4]+68*sizeof(int);
    
    	//Записываем количество данных
    	fwrite(&num1,sizeof(int),1,f);
    	//Записываем смещения
    	fwrite(offset,sizeof(int),6,f);
    	//Записываем данные
    	fwrite(mas1,sizeof(int),50,f);
    	fwrite(mas2,sizeof(int),32,f);
    	fwrite(mas3,sizeof(int),10,f);
    	fwrite(mas4,sizeof(int),8,f);
    	fwrite(mas5,sizeof(int),68,f);
    
    	delete []mas1;
    	delete []mas2;
    	delete []mas3;
    	delete []mas4;
    	delete []mas5;
    	delete []offset;
    	fclose(f);
    }

    Чтение 3-его массива можно реализовать так:

    FILE* f;
    f=fopen("MyfileOut.dat","r");
    int num2;
    if(f)
    {
    	//Считываем количество данных
    	fread(&num2,sizeof(int),1,f);
    	int *offset2 = new int[num2+1];
    	//Считываем таблицу смещений
    	fread(offset2,sizeof(int),num2+1,f);
    
    	//Вычисляем размер массива для данных
    	int n = (offset2[3]-offset2[2])/sizeof(int);
    	int *mas = new int[n];
    	//Переходим на нужную позицию
    	fseek(f,offset2[2], SEEK_SET);
    
    	//Считываем данные
    	fread(mas,sizeof(int),n,f);
    	cout<<n<<endl<<endl;
    	for(int i=0; i<n; i++)
    		cout<<mas[i]<<endl;
    	delete[]mas;
    	fclose(f);
    }

    • Предложено в качестве ответа Skimin0k 23 ноября 2010 г. 11:10
    • Помечено в качестве ответа Jualy 25 ноября 2010 г. 8:09
    23 ноября 2010 г. 11:04
  • Вообще-то есть классика. Т.н. Структуры переменного размера.

    Общая идея такова.

    struct Common

    {

    int Type;

    __int64 Size;

    __int64 Offset;

    };

    struct Var : Common

    {

    char Data[1];

    };

    поле Type - тип записи

          Size - размер переменного блока данных

         Offset - смещение в байтах к следующей структуре в файле, которая содержит данные того же типа

         Data - блок данных переменной длинны

    Например, необходимо хранить данные размером N байт:

    Var *p;

    p=(Var *)new char[sizeof(Common)+N];

    p->Type=тип;

    p->Size=N;

    p->Offset=-1; // признак последней записи, модифицируется при записи следующей структуры того же типа

    memcpy(p->Data,Buffer,N);

    далее стуктура записывается в конец файла.

    Значение Offset образует что-то вроде односвязного списка. Иногда (редко) структуру дополняют "обратным " смещением, получается двусвязный список. Это облегчает навигацию в файле.

    Для индексирования создается файл (или массив в памяти) структур-индексов:

    struct Index

    {

    int Type;

    int Count;

    __int64 ArrayOffset[1];

    };

    Поле Type - тип записи

            Count - хранит количество записей (размерность массива ArrayOffset)

            ArrayOffset - массив смещений к записи

    И наконец - Массив записей:

    Index *ArrayRecord; - естественно переменной длины, его размер равен количеству типов записей.

    Может на первый взгляд сложновато, но на деле - легко и просто.

    Если массив и файл сформированы, то чтение записи становится тривиальной задачей:

    Читаем 5 запись 3-го типа (индексы от нуля!)

    fseek(f,ArrayRecord[3].ArrayOffset [5], SEEK_SET);
    Common p;

    fread(&p,sizeof(Common),1,f);

    buffer=new char[p.Size];

    fread(buffer,p.Size,1,f); // И все!

    P.S. Если создается файл индексов, то поле Common::Offset как правило не делают. Файл индексов можно записать в начало файла записей, как в предыдущеп примере, но на практике так обычно не поступают.

    В принципе можно обойтись и без этого поля и без файла индексов. Но тогда программа сильно "просядет" по скорости. 

    • Предложено в качестве ответа _Victor_42 23 ноября 2010 г. 23:38
    • Помечено в качестве ответа Jualy 25 ноября 2010 г. 8:09
    23 ноября 2010 г. 22:52
  • P.P.S. Поля Data[1]  и ArrayOffset[1] - объявляются как массивы из одного элемента!

    Формирование таких файлов удобно выполнять при помощи списков или STL-вских или самопальных - безразлично.

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

     

    • Помечено в качестве ответа Jualy 25 ноября 2010 г. 8:09
    23 ноября 2010 г. 23:17

Все ответы

  • А в чем собственно проблема? Открыли бинарный файл для чтения или для чего вам надо сделали все манипуляции и закрыли файл.

    На каком языке?

    15 ноября 2010 г. 23:02
  •  я пишу на языке visual c++, можете привести простой пример?

    Мне data файл нужен для загрузки/выгрузки фотографи!

    17 ноября 2010 г. 8:16
  • Jualy , не могли бы Вы более подробно описать проблему, тогда всем будет понятней и решение найдется быстрее, и формат файла .data - что это за формат?
    Для связи [mail]
    19 ноября 2010 г. 7:24
  • Я Ощибся , там *.dat файл, я бы хотел узнать как с ним рабоать примеры какие нибудь!

    В моем случай , я бы хотел  хранить и обрабатывать фото! 

    19 ноября 2010 г. 7:35
  • Начнем с того, что в них обычно хранят все что хотят и как хотят... Поскольку он не имеет определенной структуры. И все подряд создают свои файлы, которым дают расширение *.dat. Даже сохранения в Fallout хранились в этом файле :). Уточните, какая программа с ним работает? Если хранить будете только вы, то так в лоб и пишите стандартными функциями.
    • Предложено в качестве ответа _Victor_42 19 ноября 2010 г. 22:49
    19 ноября 2010 г. 16:35
  • Есть много решений и все простые.

    Если без зависимости от платформы, то что-то типа:

    FILE *f;

    char *buffer;

    __int64 size;

    f=fopen("D:\\MyPath\\MyfileIn.dat","rb");

    if(f)

    {

    //читаем

    size=_filelengthi64(fileno(f));

    buffer=malloc((long)size);

    fread(buffer,size,1,f);

    fclose(f);

    // что-то делаем с данными в buffer, не забываем о размере!

    //пишем

    f=fopen(("D:\\MyPath\\MyfileOut.dat","wb");

    if(f)

    {

    fwrite(buffer,size,1,f);

    fclose(f);

    }

    free(buffer);

    }

    Под Win-дами лучше использовать CreateFile-CloseHandle вместо fopen-fclose, ReadFile-WriteFile вместо fread-fwrite и new-delete вместо malloc-free.

    Для данного примера: stdio.h, io.h, stdlib.h

     P.S. В примере возникнет проблема при обработке файла более 2 Гб

    • Предложено в качестве ответа _Victor_42 19 ноября 2010 г. 23:03
    19 ноября 2010 г. 23:03
  • Все это я понял! Теперь вопрос такой ,  Если туда я записываю данные . То как там все индексировать ? разделить на поля ? чтобы от туда можно было вытащить данные по определенному запросу (как в Базах Данных)

    22 ноября 2010 г. 8:03
  • В таком случае реализуйте шапку: вы  можете сначала сохранять в файл количество данных, а затем их смещения относительно начала файла, а уж потом сами данные. Например, запись может выглядеть следующим образом:

    FILE* f;
    f=fopen("MyfileOut.dat","w");
    //Пусть количество хранимых данных = 5
    int num1 = 5;
    if(f)
    {	//Возьмем в качестве данных массивы разных размеров
    	int *mas1 = new int[50];
    	for(int i=0; i<50; i++)
    		mas1[i] = 1;
    	int *mas2 = new int[32];
    	for(int i=0; i<32; i++)
    		mas2[i] = 2;
    	int *mas3 = new int[10];
    	for(int i=0; i<10; i++)
    		mas3[i] = 3;
    	int *mas4 = new int[8];
    	for(int i=0; i<8; i++)
    		mas4[i] = 4;
    	int *mas5 = new int[68];
    	for(int i=0; i<68; i++)
    		mas5[i] = 5;
    	//Шапка файла
    	int *offset = new int[6];
    	//Размер шапки 7 INT, т.к. у нас первый INT хранит количество объектов, 
    	//далее будем хранить смещения от начала 5 объектов для сохранения и конец последнего. 
    	//С этой позиции начинаются первые данные.
    	offset[0]= 7*sizeof(int);
    	//С этой позиции начинаются вторые данные
    	offset[1]= offset[0]+50*sizeof(int);
    	//И т.д.
    	offset[2]= offset[1]+32*sizeof(int);
    	offset[3]= offset[2]+10*sizeof(int);
    	offset[4]= offset[3]+8*sizeof(int);
    	//Конец файла на этой позиции
    	offset[5]= offset[4]+68*sizeof(int);
    
    	//Записываем количество данных
    	fwrite(&num1,sizeof(int),1,f);
    	//Записываем смещения
    	fwrite(offset,sizeof(int),6,f);
    	//Записываем данные
    	fwrite(mas1,sizeof(int),50,f);
    	fwrite(mas2,sizeof(int),32,f);
    	fwrite(mas3,sizeof(int),10,f);
    	fwrite(mas4,sizeof(int),8,f);
    	fwrite(mas5,sizeof(int),68,f);
    
    	delete []mas1;
    	delete []mas2;
    	delete []mas3;
    	delete []mas4;
    	delete []mas5;
    	delete []offset;
    	fclose(f);
    }

    Чтение 3-его массива можно реализовать так:

    FILE* f;
    f=fopen("MyfileOut.dat","r");
    int num2;
    if(f)
    {
    	//Считываем количество данных
    	fread(&num2,sizeof(int),1,f);
    	int *offset2 = new int[num2+1];
    	//Считываем таблицу смещений
    	fread(offset2,sizeof(int),num2+1,f);
    
    	//Вычисляем размер массива для данных
    	int n = (offset2[3]-offset2[2])/sizeof(int);
    	int *mas = new int[n];
    	//Переходим на нужную позицию
    	fseek(f,offset2[2], SEEK_SET);
    
    	//Считываем данные
    	fread(mas,sizeof(int),n,f);
    	cout<<n<<endl<<endl;
    	for(int i=0; i<n; i++)
    		cout<<mas[i]<<endl;
    	delete[]mas;
    	fclose(f);
    }

    • Предложено в качестве ответа Skimin0k 23 ноября 2010 г. 11:10
    • Помечено в качестве ответа Jualy 25 ноября 2010 г. 8:09
    23 ноября 2010 г. 11:04
  • Вообще-то есть классика. Т.н. Структуры переменного размера.

    Общая идея такова.

    struct Common

    {

    int Type;

    __int64 Size;

    __int64 Offset;

    };

    struct Var : Common

    {

    char Data[1];

    };

    поле Type - тип записи

          Size - размер переменного блока данных

         Offset - смещение в байтах к следующей структуре в файле, которая содержит данные того же типа

         Data - блок данных переменной длинны

    Например, необходимо хранить данные размером N байт:

    Var *p;

    p=(Var *)new char[sizeof(Common)+N];

    p->Type=тип;

    p->Size=N;

    p->Offset=-1; // признак последней записи, модифицируется при записи следующей структуры того же типа

    memcpy(p->Data,Buffer,N);

    далее стуктура записывается в конец файла.

    Значение Offset образует что-то вроде односвязного списка. Иногда (редко) структуру дополняют "обратным " смещением, получается двусвязный список. Это облегчает навигацию в файле.

    Для индексирования создается файл (или массив в памяти) структур-индексов:

    struct Index

    {

    int Type;

    int Count;

    __int64 ArrayOffset[1];

    };

    Поле Type - тип записи

            Count - хранит количество записей (размерность массива ArrayOffset)

            ArrayOffset - массив смещений к записи

    И наконец - Массив записей:

    Index *ArrayRecord; - естественно переменной длины, его размер равен количеству типов записей.

    Может на первый взгляд сложновато, но на деле - легко и просто.

    Если массив и файл сформированы, то чтение записи становится тривиальной задачей:

    Читаем 5 запись 3-го типа (индексы от нуля!)

    fseek(f,ArrayRecord[3].ArrayOffset [5], SEEK_SET);
    Common p;

    fread(&p,sizeof(Common),1,f);

    buffer=new char[p.Size];

    fread(buffer,p.Size,1,f); // И все!

    P.S. Если создается файл индексов, то поле Common::Offset как правило не делают. Файл индексов можно записать в начало файла записей, как в предыдущеп примере, но на практике так обычно не поступают.

    В принципе можно обойтись и без этого поля и без файла индексов. Но тогда программа сильно "просядет" по скорости. 

    • Предложено в качестве ответа _Victor_42 23 ноября 2010 г. 23:38
    • Помечено в качестве ответа Jualy 25 ноября 2010 г. 8:09
    23 ноября 2010 г. 22:52
  • P.P.S. Поля Data[1]  и ArrayOffset[1] - объявляются как массивы из одного элемента!

    Формирование таких файлов удобно выполнять при помощи списков или STL-вских или самопальных - безразлично.

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

     

    • Помечено в качестве ответа Jualy 25 ноября 2010 г. 8:09
    23 ноября 2010 г. 23:17