Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Хранение информации


Автор: artsb 11.5.2008, 15:23
Перенимаю опыт. smile

Мне в приложении нужно хранить во время работы, записывать в файл и считывать из файла много "блоков" информации. Я решил эту проблему так:
Код

//Создал структуру:
struct myList
{
AnsiString name;
AnsiString path;
int count;
bool flag;
};
//Создал вектор:
#include <vector.h>
...
vector<myList> list;

И далее работаю с вектором. Сохраняю данные в цикле в ini файл со своим расширением. Естественно, это не практично и не безопасно: "умный" пользователь может открыть файл блокнотом и нагадить там.
Как вы работаете с информацией и файлами в таких случаях?
Спасибо всем за участие!

Автор: Rrader 11.5.2008, 15:29
Криптуем данные smile 

Автор: artsb 11.5.2008, 15:42
Rrader, выложи ссылки по этой теме, если не тяжело.

Автор: Rrader 11.5.2008, 15:51
http://www.ssl.stu.neva.ru/psw/crypto/appl_rus/appl_cryp.htm

Добавлено через 2 минуты и 25 секунд
http://www.cyberguru.ru/cpp-sources/algorithms/shifrovanie-metodom-xor.html

Автор: artsb 11.5.2008, 16:48
Rrader, спасибо. xor'ом я пользовался уже. А, вообще, криптография это не совсем то, что я имел ввиду (но всё равно полезно). Я имею ввиду, как можно сохранять файлы с большим количеством информации компактно и надёжно (недоступно для пользователя).

Автор: Rrader 11.5.2008, 17:28
Можешь использовать zlib для сжатия. Очень удобно.

Автор: artsb 11.5.2008, 19:10
Цитата(Rrader @  11.5.2008,  17:28 Найти цитируемый пост)
Можешь использовать zlib для сжатия. Очень удобно.

Тоже вариант.

Автор: orthrus 12.5.2008, 07:21
Может тебе тут лучше использовать локальную БД(например SQLite или Firebird Embedded), и структура файла там чуток сложнее чем в ini файле, тем более что нужно
Цитата(artsb @  11.5.2008,  15:23 Найти цитируемый пост)
записывать в файл и считывать из файла много "блоков" информации

Автор: ksili 12.5.2008, 10:26
Сжатый или криптованный файл пользователь тоже может открыть в блокноте и нагадить там. Другое дело, что он не сможет нагадить осмысленно smile 
Использовать БД думаю наиболее оптимально. Вдруг в дальнейшем понадобится совершать поиск по этим данным - СУБД в этом поможет.

Чтоб юзер не мог править файл, записанный твоей прогой можно попробовать сдлеать так: создаешь пользователя с паролем. Запускаешь свою прогу от его имени (можно прописать в ярлыке). Прога пишет свои файлы в папку документов этого пользователя. А другой пользователь их прочесть не может, т.к. Windows не даст зайти в эту папку.

Автор: xvr 12.5.2008, 14:00
Цитата(artsb @ 11.5.2008,  16:48)
Rrader, спасибо. xor'ом я пользовался уже. А, вообще, криптография это не совсем то, что я имел ввиду (но всё равно полезно). Я имею ввиду, как можно сохранять файлы с большим количеством информации компактно и надёжно (недоступно для пользователя).

Запиши данные в файловый стрим (имя файла в виде "qqq:mydata"), пользователь увидит только файл qqq нулевой длинны.

Автор: artsb 12.5.2008, 23:08
Цитата(ksili @  12.5.2008,  10:26 Найти цитируемый пост)
Другое дело, что он не сможет нагадить осмысленно

Я о том же.
Цитата(xvr @  12.5.2008,  14:00 Найти цитируемый пост)
Запиши данные в файловый стрим (имя файла в виде "qqq:mydata"), пользователь увидит только файл qqq нулевой длинны.

Вот это интересно, правда непонятно.
xvr, объясни плиз. Если можно на конкретном примере.

Пробовал с помощью функций fread и fwrite записывать структуру в файл поблоково. Но почему-то они не хотят рабоать с AnsiString, а char меня не устраивает. Как быть?

Автор: xvr 13.5.2008, 07:57
Цитата(artsb @ 12.5.2008,  23:08)
Цитата(ksili @  12.5.2008,  10:26 Найти цитируемый пост)
Другое дело, что он не сможет нагадить осмысленно

Я о том же.
Цитата(xvr @  12.5.2008,  14:00 Найти цитируемый пост)
Запиши данные в файловый стрим (имя файла в виде "qqq:mydata"), пользователь увидит только файл qqq нулевой длинны.

Вот это интересно, правда непонятно.
xvr, объясни плиз. Если можно на конкретном примере.

MSDN: A Programmer's Perspective on NTFS 2000 Part 1: Stream and Hard Link
Цитата

Under an NTFS file system each file can have multiple streams of data. It's worth pointing out that streams are not a feature of NTFS 2000, but they have been in existence since Windows NT 3.1. When you read the content of a file under a non-NTFS volume (say, a disk partition of a Windows 98 machine) you're able to access only one stream of data. Consequently, you perceive it as the real and "unique" content for that file. Such a main stream has no name and is the only one that non-NTFS file systems can handle. But when you create a file on an NTFS volume, things might be different.
A multi-stream file is a sort of collection of single-stream files all embedded in the same file system entry. They definitely look like a unique and atomic unit, yet comprise a number of independent sub-units you can create, delete, and modify separately. There are a number of common programming scenarios where streams are more than handy. However, if you plan to use them, bear in mind that as soon as you copy a multi-stream file to a non-NTFS storage device (such as a CD, a floppy, or a non-NTFS disk partition), all extra streams will be unrecoverable if lost. Unfortunately, such a compatibility issue makes streams much less attractive in practice. For server-side applications designed and destined to run only on NTFS volumes, streams are an excellent tool to leverage to build great and creative solutions.
To identify a named stream within a file you should follow a particular naming convention and add at the end of the file name a colon followed by the stream name. For example, to access a stream called VersionInfo on a file called test.txt you should use the file name:
   Test.txt:VersionInfo
Use it with any Microsoft Win32® API function that manipulates files. To access the content of the VersionInfo stream, pass that name on to CreateFile() and then use ReadFile() and WriteFile() to accomplish reading and writing as usual. If you want to check whether a certain stream exists within a file, compose the file stream name as just shown and use CreateFile() to check it for existence:
Код

HANDLE hfile = CreateFile(szFileStreamName, GENERIC_READ, 0, 
   NULL, OPEN_EXISTING, 0, 0);
CloseHandle(hfile);
if (hfile == NULL)
   MessageBox(hWnd, "Error", NULL, MB_OK);


Цитата

Пробовал с помощью функций fread и fwrite записывать структуру в файл поблоково. Но почему-то они не хотят рабоать с AnsiString, а char меня не устраивает. Как быть?

Запись:
Код

AnsiString data=...;
fwrite(data.c_str(),1,data.size(),file);

Чтение:
Код

fseek(file,0,SEEK_END);
int fsize=ftell(file);
fseek(file,0,SEEK_SET);
AnsiString data=AnsiString::StringOfChar(' ',fsize);
fread(data.c_str(),1,fsize,file);


Автор: SABROG 13.5.2008, 08:45
А как затестить рабочесть этой технологии стандартными средствами винды, т.е. блокнот там, консоль. Чтобы не пришлось писать на WinApi ?

Автор: ksili 13.5.2008, 08:51
Цитата(SABROG @  13.5.2008,  12:45 Найти цитируемый пост)
А как затестить рабочесть этой технологии стандартными средствами винды, т.е. блокнот там, консоль. Чтобы не пришлось писать на WinApi ?

FAR кажется понимает альтернативные потоки и может их читать

Автор: SABROG 13.5.2008, 08:56
Во че нашел http://www.securitylab.ru/analytics/216379.php

Автор: xvr 13.5.2008, 12:22
Цитата(SABROG @ 13.5.2008,  08:45)
А как затестить рабочесть этой технологии стандартными средствами винды, т.е. блокнот там, консоль. Чтобы не пришлось писать на WinApi ?

Открываешь консоль (cmd.exe) и набираешь:
Код

echo some text > test:tst
sort < test:tst

В папке после этого остается файл test нулевой длинны, в котором есть поток tst с текстом some test
Так же можно в FAR'е нажать Shift-F4, в открывшемся имени файла для редактирования набрать test:tst и написать туда что хочешь. Смотреть аналогично (снова через Shift-F4)

Автор: SABROG 13.5.2008, 12:42
Спс. Заметил, что огромное количество графических файлов имеют подобные потоки. Походу дела эскизы. А некоторые файлы имеют Zone.Identifier:
Код

C:\>sort < c:\Downloads\000901.gif:Zone.Identifier
[ZoneTransfer]
ZoneId=3


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

Вот еще интересная штука:

Код

C:\>sort < c:\winnt\win.ini:s1
2400

Автор: artsb 13.5.2008, 16:21
Цитата

Запись:
Код

AnsiString data=...;
fwrite(data.c_str(),1,data.size(),file);

Чтение:
Код

fseek(file,0,SEEK_END);
int fsize=ftell(file);
fseek(file,0,SEEK_SET);
AnsiString data=AnsiString::StringOfChar(' ',fsize);
fread(data.c_str(),1,fsize,file);


Это мне не подходит :(
Я использую структуру:
Код

struct mList
{
AnsiString str1;
AnsiString str2;
int a1;
int a2;
///...
}

Записываю и считываю так:
Код

// записываю

strcpy(sett.info,Edit6->Text.c_str());
sett.time=Edit5->Text.ToInt();
sett.n1=Edit7->Text.ToInt();
sett.n2=Edit8->Text.ToInt();
sett.col=list.size();
FILE* f=fopen("myfile.rer","wb");
if(!f) return;
fwrite(&sett,sizeof(mSettings),1,f);
int n=list.size();
for(int i=0;i<n;i++)
        fwrite(&list[i],sizeof(mList),1,f);
fclose(f);

// читаю

FILE* f=fopen("myfile.rer","rb");
if(!f) return;

fread(&sett,sizeof(mSettings),1,f);

Edit6->Text=sett.info;
Edit5->Text=sett.time;
Edit7->Text=sett.n1;
Edit8->Text=sett.n2;

for(int i=0;i<sett.col;i++)
{
        mList temp;

        fread(&temp,sizeof(mList),1,f);
        list.push_back(temp);
        ListBox1->Items->Add(temp.name);
}
fclose(f);

// здесь sett - это тоже структура
//     list - вектор структур mList

Числа записываются и считываются нормально. А вот строки не хотят.

Автор: xvr 13.5.2008, 18:00
Цитата(artsb @ 13.5.2008,  16:21)
Это мне не подходит :(
Я использую структуру:
Код

struct mList
{
AnsiString str1;
AnsiString str2;
int a1;
int a2;
///...
}

  •  Структуру, содержащую вложенные классы (а AnsiString именно таковым и является) нельзя записывать целиком как образ памяти, нужно писать по полям.
  •  fopen("myfile.rer",...); замени на fopen("myfile.rer:data",...); и будет тебе счастье  smile

Автор: artsb 13.5.2008, 21:51
Цитата(xvr @  13.5.2008,  18:00 Найти цитируемый пост)
 fopen("myfile.rer",...); замени на fopen("myfile.rer:data",...);

а что это изменит?

Автор: xvr 13.5.2008, 22:09
Цитата(artsb @ 13.5.2008,  21:51)
Цитата(xvr @  13.5.2008,  18:00 Найти цитируемый пост)
 fopen("myfile.rer",...); замени на fopen("myfile.rer:data",...);

а что это изменит?

Данные будут записываться в stream с именем data, сам файл myfile.rer при этом будет выглядеть пустым

Автор: SABROG 13.5.2008, 22:13
Цитата(artsb @ 13.5.2008,  21:51)
Цитата(xvr @  13.5.2008,  18:00 Найти цитируемый пост)
 fopen("myfile.rer",...); замени на fopen("myfile.rer:data",...);

а что это изменит?

Это ответ на твой вопрос о том, чтобы юзеры шаловливыми ручками не меняли настройки программы. При желании можно даже файла не создавать, обычная директорию тоже имеет альтернативные потоки. Только при этой технологии твоя программа больше нигде не будет корректно работать кроме как на файловой системе NTFS.

Имхо лучше шифрануть файлик паролем юзера, расшифровываться будет на-лету. Если пароль не верный - не верно расшифруется и настройки будут битыми, вернее будет мусор.

Автор: artsb 13.5.2008, 22:24
А. Понятно. Спасибо.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)