Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Файлы и Tstrings, Можно ли создать типизированный файл? 
:(
    Опции темы
AndreyANM
Дата 27.1.2006, 12:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 4.1.2006

Репутация: нет
Всего: нет



Можно ли создать типизированный файл, в котором
будут храниться переменные типа TStrings (а точнее записи содержащие
такие переменные)?
Я думаю, что нет, но компилятор при определении такого файла
никакой ошибки не выдает.

Type
Rec= Record
A,B,C:Integer;
S:TStrings;
End;

Var
F:File of rec;

Будет ли такой файл действительно содержать строки TStrings (S)?
PM MAIL   Вверх
Snowy
Дата 27.1.2006, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Нет, не будет.
Вместо него полцчишь красивые 4 байта, которые при последующей загрузке будут выдвать Access Violation.
PM MAIL   Вверх
AndreyANM
Дата 27.1.2006, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 4.1.2006

Репутация: нет
Всего: нет



Цитата

Нет, не будет.
Вместо него полцчишь красивые 4 байта, которые при последующей загрузке будут выдвать Access Violation.


Как же можно выкрутиться в таком случае?

Пока - что я использую в файле вместо TStrings массив строк (array [1..10] of string[255] - мне этого достаточно).
Но это не совсем рационально.

Может есть еще какие - нибудь способы хранить в файле текст и дополнительные переменные?
PM MAIL   Вверх
Snowy
Дата 27.1.2006, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



XML
PM MAIL   Вверх
ShadeSt
Дата 27.1.2006, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 9.8.2005
Где: Россия, г. Ставро поль

Репутация: нет
Всего: 7



У TStrings есть методы SaveToFile и LoadFromFile.
Можно упростить (или усложнить) структуру. Вобщем сделать так что первые три строки в файле - это будут переменные A, B,C, а дальше будут идти необходимые строки.
Программно можно пропускать эти первые три строки и работать с остальным содержимым, либо же выполнив LoadFromFile выбрать первые три строки и присвоить их значение переменным A,B,C
Код

Var
  TS : TStrings;
.....
  A := StrToInt( TS[0])
  TS.Delete[0];
  B := StrToInt( TS[1])
  TS.Delete[1];
  C := StrToInt( TS[2])
  TS.Delete[2];

Таким образом в TS останется только необходимый текст.
Либо же как сказал Snowy можно использовать XML, только на мой взгляд немного сложнее будет.
Добавлено @ 16:57
Вот примерно так:
Код

Type
 TRec = Record
   A, B, C : Integer;
   S       : TStrings;
  End;


procedure TForm1.Button2Click(Sender: TObject);
Var
  MyRec : TRec;
begin
  FillChar(MyRec, SizeOf(TRec), 0);
  MyRec.S := TStringList.Create;
  MyRec.S.LoadFromFile('c:\222');

  MyRec.A := StrToIntDef(MyRec.S[0], 0);
  MyRec.S.Delete(0);

  MyRec.B := StrToIntDef(MyRec.S[0], 0);
  MyRec.S.Delete(0);

  MyRec.C := StrToIntDef(MyRec.S[0], 0);
  MyRec.S.Delete(0);


  MyRec.S.Free;
end;


Только в файлике должно быть не менее 3х строк.
Только, наверное лучше будет сделать класс, вместо записи, у котороко в конструкторе инициализировать TStrings, а также у него же сделать методы загрузки данных и сохранения данных и уже потом работать с этим объектом.


--------------------
It's nice to be importand, but it's more importand to be nice © Scooter
PM MAIL ICQ Jabber   Вверх
Guedda
Дата 27.1.2006, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Подрывник
****


Профиль
Группа: Завсегдатай
Сообщений: 3137
Регистрация: 27.12.2005
Где: Ростов-на-Дону

Репутация: 14
Всего: 78



Создать типизированный бинарный файл и работать с ним, типа:
Код

type
  TBinFl = file of byte;
   WorData = record
      Smesh : DWORD; //смещение, полученное в результате заноса строки
      ID : DWORD; //ID строки
   end;


Пишешь:
Цитата

Данные = WorData = Строка = WorData = Строка = WorData = ...


Читаешь:
Цитата

Данные пока не WorData,
WorData = строка = WorData = Строка ...



--------------------
Ll 2
PM MAIL WWW ICQ Skype GTalk   Вверх
Guedda
Дата 27.1.2006, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Подрывник
****


Профиль
Группа: Завсегдатай
Сообщений: 3137
Регистрация: 27.12.2005
Где: Ростов-на-Дону

Репутация: 14
Всего: 78



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

Попробую сформулировать своё видение твоей задачи.

ЗАДАЧА

Цитата:
Мне нужно сделать, чтобы картинки сохранялись в один файл, и по требованию пользователя загружались из этого файла (например в память). И считывая картинки из памяти программа показывает их в TImage по порядку с заданным интервалом. Короче
программа-слайдшоу.

ОБЩИЙ ПЛАН

Придумываем свой формат файла (бинарный естественно).
- Изображения ложатся в файл друг за другом. Считываются так же.
- При чтении нужно знать, сколько занимает считываемая картинка. Варианты:
а) писать перед каждой картинкой её размер (одно целое число);
б) записать вначале список, содержащий размеры всех картинок, возможно, их смещения в файле.
Первый способ самый простой и понятный. Но второй более универсальный. Он даёт возможность хранить список имеющихся изображений, возможность произвольного доступа к любой из них.
Для начинающих лучше было бы избрать первый вариант. Но я тут предпочту второй. Не люблю тупиковых направлений.
- Обычно в бинарных форматах, в самом начале, помещают заголовок файла. Сделаем и мы его. Запишем туда какую-то сигнатуру (чтобы проверять, что файл «свой») и количество изображений. Можно зарезервировать немного места для каких-то будущих расширений формата, например, добавление картинок без перезаписи файла.

ФОРМАТ ФАЙЛА

Файл состоит из следующих частей, расположенных друг за гругом

Код
 

1. Заголовок 

Код:    
TFileHead = packed record 
  Signature:   Array [1..2] of Char;  // тут пишем ’IL’ – Images List 
  Version:     Array [1..2] of Byte;  // на будущее, пока 0,0 
  RecordCount: DWord;                 // количество картинок в файле 
  Reserve:     Array [1..24] of Byte; 
end;    
Всего вышло 32 байта на заголовок 

2. Список картинок 
Последовательность лежащих друг за другом записей : 

Код:    
TFileItemDescr = packed record 
  Offset: DWord;                 // Смещение картинки в файле 
  Size:   DWord;                 // Её размер 
  Kind:   Array [1..3] of Char;  // Тип (расширение) 
  Name:   String[20];            // Если захочется хранить имя 
end;    
Каждая запись описывает одну из картинок, лежащих в теле файла. Количество записей задаётся параметром RecordCount заголовка. Таким образом, длинна этой части файла SizeOf(TFileItemDescr) * RecordCount. 

3. Тело файла, сами картинки. 
При записи сюда ложатся друг за другом картинки. Их местоположения записаны во 2-й части формата. 

Замечания 
а. Используются packed record, а не просто record для того, чтобы копилятор не пытался выравнивать поля, не вставлял «дырок» между ними. 
б. Строки можно хранить только как массив байтов или как короткие строки (указывается длинна). Если короткая строка, нужно иметь ввиду, что один байт отводится на хранение длинны строки. 

АЛГОРИТМ ЗАПИСИ 

Предполагаем, что у нас есть список файлов, содержащих картинки, которые нужно собрать в один файл «нашего» формата. Будем работать с файлом через TFileStream. Его интерфейс самый простой. 

1. Описываем базовые переменные 

Код:    
var 
  Head: TFileHead; 
  List: Array of TFileItemDescr; 

Заполняем их 
ZeroMemory( @Head, SizeOf(Head) ); 
Head.Signature[1] := ‘I’; 
Head.Signature[1] := ‘I’; 
Head.RecordCount := … 
SetLength( List, … );    

2. Открываем файл, пишем первые два блока. Второй блок пока пустой, мы просто зарезервируем место в файле. 

Код:    
var F: TFileStream; 
F := TFileStream.Create( ‘…’, fmCreate   ); 
F.Write( Head, SizeOf(Head) ); 
F.Write( List[0], SizeOf(TFileItemDescr) * Head.RecordCount );  

3. Пишем картинки. 
Заведём для доступа к ним отдельный поток. 

Код:    
var 
  Fi: TFileStream; 
  i,n: Integer; 
... 
for i:=0 to … do 
begin 
  Fi := TFileStream.Create( ‘…’, fmOpenRead ); 
  n := Fi.Size; 
  List[i].Offset := F.Position; 
  List[i].Size   := n; 
  List[i].Kind   := ‘…’; 
  F.CopyFrom( Fi, n ); 
  Fi.Free; 
end;    

4. Сохранение списка 
Теперь 2-й блок нашего файла заполнен. Запишем его на место. 

Код:    
F.Seek( SizeOf(Head), soFromBeginning ); 
F.Write( List[0], SizeOf(TFileItemDescr) * Head.RecordCount );  

Всё. Файл записан. 

АЛГОРИТМ ЧТЕНИЯ 

1. Открываем файл. Проверяем, что это «наш» файл, читаем список. 

Код:    
var 
  Head: TFileHead; 
  List: Array of TFileItemDescr; 
  F: TFileStream; 

F := TFileStream.Create( ‘…’, fmOpenRead ); 
F.Read( Head, SizeOf(Head) ); 
if (Head.Signature <> ‘IL’ ) then raise … 
if (Head.Vervion[1] <> 0) or (Head.Vervion[2] <> 0) then raise … 
SetLength( List, Head.RecordCount ); 
F.Read( List[0], SizeOf(TFileItemDescr) * Head.RecordCount );    

2. Чтение картинки. 
Наш формат файла предусматривает возможность чтения произвольной картинки 

Код:    
function Xxx.LoadImage( Index: Integer ): TGraphic; 
var 
  Fi: TMemoryStream; 
begin 
with List[Index] do 
begin 
  Result := nil; 
  If Kind = ‘bmp’ then Result := TBitmap.Create else 
  if Kind = ‘jpg’ then Result := TJPEGImage.Create else 
  Exit; 
  F.Seek( Offset, soFromBeginning ); 
  Fi := TMemoryStream.Create; 
  Fi.CopyFrom( F, Size ); 
  Fi.Offset( 0, soFromBeginning ); 
  Result.LoadFromStream( Fi ); 
  Fi.Free; 
end; 
end;


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


--------------------
Ll 2
PM MAIL WWW ICQ Skype GTalk   Вверх
Bose
Дата 27.1.2006, 18:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1458
Регистрация: 5.3.2005
Где: Riga, Latvia

Репутация: 23
Всего: 51



а еще можно создать (не)типизированный бинарный файл и писать через TFileStream. Перед каждым обьектом записывать его размер. А перед каждым размером писать какой-нибудь идентификатор, по которому при загрузке можно будет определить, что за обьект надо считать.

По такому принципу сделано сохранение/загрузка дерева в Virtual Treeview. Очень удобно, если есть разветвлённая иерархия классов(обьектов). Основную процедуру сохранения можно реализовать в базовом классе, Переопределяя этот метод в наследниках, можно усложнять структуру данных не меняя структуры файла.
PM MAIL WWW Skype   Вверх
AndreyANM
Дата 27.1.2006, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 57
Регистрация: 4.1.2006

Репутация: нет
Всего: нет



Всем спасибо, буду разбираться...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1795 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.