Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2010.11.07;
Скачать: [xml.tar.bz2];

Вниз

Неясности в формате файла   Найти похожие ветки 

 
Виталий ©   (2010-07-12 22:59) [160]

Нет, я адекватно воспринимаю критику, просто немного растерялся. Теперь я собран и больше этого не повторится.


 
Anatoly Podgoretsky ©   (2010-07-12 23:01) [161]

> Sha  (12.07.2010 22:38:27)  [147]

Не так просто, тем более что Юрий побеспокоился, а ты еще и масла подлил.
Но на мой взгляд он выбрал неверное решение,ему следовало бы сначала решить
это с помощью файлов Паскаля (текстовых), а потом как домашнее задание с
помощью файловых потоков, а на закуску MMF

Ведь выбор оптимального решения входит в мастерство. В умение решать задачи
разными путями. Во взрастание специалиста.


 
Anatoly Podgoretsky ©   (2010-07-12 23:02) [162]

> Виталий  (12.07.2010 22:42:30)  [150]

Правильно, так и есть, только цели ты неверно определил.
В конце концов ты же сам напросился, ты в любой момент можешь отказаться.


 
Виталий ©   (2010-07-12 23:03) [163]


> MMF

Я хотел бы, если на данный момент это не скачок, чтобы вы подсказали более подробную работу с ними, чем то, что описано в книгах. Или только MSDN?


 
Виталий ©   (2010-07-12 23:04) [164]


> ты в любой момент можешь отказаться

я, может, и глупый, но упорный. Не откажусь.


 
Anatoly Podgoretsky ©   (2010-07-12 23:05) [165]

> Виталий  (12.07.2010 22:43:31)  [151]

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


 
Sha ©   (2010-07-12 23:06) [166]

1. Проблема возникает из-за того, что ты сам решил писать в файл мусор. Нафига туда писать указатели, причем пустые?

2. Проблема возникнет при чтении, т.к. ты этот мусор еще зачем-то читаешь.
Если в момент установки длины строки ее указатель в записи будет содержать
непустое значение, то будет сделана попытка перераспределения памяти
и получено AV. Проблему лучше решать по месту возникновения, например
pointer(test.FirstName):=nil; перед установкой длины.

3. Ну и вообще в это поле удобно было бы писать длину строки.


 
Anatoly Podgoretsky ©   (2010-07-12 23:06) [167]

> Виталий  (12.07.2010 22:53:35)  [155]

Правильно говорит и ты это должен иметь в виду, но выбери приоритеты, разбей
задачу по этапам. Ведь ты же учишься и хочешь этого?


 
Anatoly Podgoretsky ©   (2010-07-12 23:07) [168]

> Виталий  (12.07.2010 22:57:38)  [158]

Не надо проверять ввод пользователя, пустое значение - нормальное значение,
надо писать так, что бы не возникало проблем (ошибок) из-за этого.


 
Sha ©   (2010-07-12 23:10) [169]

> Anatoly Podgoretsky ©   (12.07.10 23:01) [161]
> на закуску MMF

Страничная организация данных не предполагает обязательное использование MMF.
Например, MS SQL Server работает через порты завершения.


 
Юрий Зотов ©   (2010-07-12 23:10) [170]

> Виталий

1. Почему тип структуры объявлен внутри класса, да еще в секции private?

Впрочем, это к теме не относится.

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

2. Писать пустую структуру в файл - незачем (поэтому переменные s, s1, s2 - лишние, можно писать прямо из test^). Читать пустую структуру тоже незачем. То ли в статье что-то не так написано, то ли Вы что-то не так поняли.

3. Нет записи и чтения BirthDate. Дата (и любые другие данные фиксированной длины) пишется и читается так же, как и строки - только длина известна заранее: SizeOf(TDate), поэтому писать сначала длину незачем, можно писать сразу сами данные.

4. Не хватает двух блоков try-finally. Общая схема всегда такая:
захват_ресурса;
try
 работа_с_ресурсом;
finally
 освобождение_ресурса;
end;

В данном случае мы дважды захватываем память - при создании стрима и структуры. Значит, должно быть так:

Stream := TFileStream.Create(...);
try
 New(test);
 try
   ...
 finally
   Dispose(test);
 end;
finally  
 Stream.Free;
end;

==================

Ну и на закуску: вот работающий код. Сравните со своим - никаких принципиальных различий. Поэтому - кто сказал, что Ваш код плохой? Нормальный код, и не надо комплексовать, нет для этого причины.

procedure TForm1.btnSaveClick(Sender: TObject);
var
 test: PFriend;
 Stream: TFileStream;
 len: integer;
begin
 Stream := TFileStream.Create("D:\temp\test.dat", fmCreate);
 try
   New(test);
   try
     test^.FirstName := "Иван";
     test^.LastName := "Петров";
     test^.BirthDate := Now;
     test^.Phone := "222-22-22";
     len := Length(Test^.FirstName);
     Stream.WriteBuffer(len, sizeof(len));
     Stream.WriteBuffer(pChar(Test^.FirstName)^, len);
     len := Length(test^.LastName);
     Stream.WriteBuffer(len, sizeof(len));
     Stream.WriteBuffer(pChar(test^.LastName)^, len);
     Stream.WriteBuffer(Test^.BirthDate, SizeOf(TDate));
     len := Length(Test^.Phone);
     Stream.WriteBuffer(len, sizeof(len));
     Stream.WriteBuffer(pChar(Test^.Phone)^, len);
   finally
     Dispose(test);
   end;
 finally
   Stream.Free;
 end
end;

procedure TForm1.btnLoadClick(Sender: TObject);
var
 Stream: TFileStream;
 test: PFriend;
 len: Integer;
begin
 Stream := TFileStream.Create("D:\temp\test.dat", fmOpenRead);
 try
   New(test);
   try
     Stream.ReadBuffer(len, sizeof(len));
     SetLength(test^.FirstName, len);
     Stream.ReadBuffer(pChar(test^.FirstName)^,Len);
     Stream.ReadBuffer(len, sizeof(len));
     SetLength(test^.LastName, len);
     Stream.ReadBuffer(pChar(test^.LastName)^,Len);
     Stream.ReadBuffer(test^.BirthDate, SizeOf(TDate));
     Stream.ReadBuffer(len, sizeof(len));
     SetLength(test^.Phone, len);
     Stream.ReadBuffer(pChar(test^.Phone)^,Len);
     ShowMessage(test^.FirstName+" "+test^.LastName+" "+DateToStr(test^.BirthDate)+" "+test.Phone);
   finally
     dispose(test);
   end;
 finally
   Stream.Free;
 end
end;


 
Виталий ©   (2010-07-12 23:14) [171]


> Как
> только не понравилось, хлопни стопочку, глядишь к концу
> чтения, будешь
> полностью согласен с нами и песни петь начнешь.

Спасибо, не пью.

> Нафига туда писать указатели, причем пустые?

В этом случае, насколько я понимаю, я должен отказаться от удобства писать структуру целиком (скажем, у меня только 3 поля текстовые и 20 - других типов) и писать поле за полем?

А вот это, простите, не понял:
> Проблему лучше решать по месту возникновения, например
> pointer(test.FirstName):=nil; перед установкой длины.

Не будет там непустого значения, разве что кто-то намерено повредит файл записей. Но можно сделать и так, а при сохранении не обнулять - что изменится-то?


 
Sha ©   (2010-07-12 23:17) [172]

> Юрий Зотов ©   (12.07.10 23:10) [170]
> 3. Нет записи и чтения BirthDate.

Для этого он и пишет структуру целиком


 
Юрий Зотов ©   (2010-07-12 23:18) [173]

Да, я это уже позже понял. Кстати, тоже очень неплохая идея.


 
Виталий ©   (2010-07-12 23:18) [174]


> Писать пустую структуру в файл

Именно хотел попробовать работу записи структуры сразу, а не по ее полям один за другим.

> Нет записи и чтения BirthDate

когда записывается вся структура, то это поле запишется вместе с ней (и потом считается), у меня по крайней мере вывелось значение
Ваш код прочел, понял, да, насчет try...finally не подумал, но это в принципе более-менее известная мне техника.


 
Виталий ©   (2010-07-12 23:20) [175]


> Страничная организация данных не предполагает обязательное
> использование MMF.
> Например, MS SQL Server работает через порты завершения.
>

Уже знаю, вы меня сбиваете :) Я не знаю, что такое порты завершения, но если будет литература и необходимость - попробую осилить.


 
Sha ©   (2010-07-12 23:23) [176]

> В этом случае, насколько я понимаю, я должен отказаться от удобства писать структуру целиком

Нет. Просто пиши длину строки вместо указателя.


> Но можно сделать и так, а при сохранении не обнулять - что изменится-то?

Очень многое.
Это все равно, что в одной процедуре присвоить значение глобальной переменной,
а в другой его использовать. Если возможно, таких вещей надо избегать.


 
Sha ©   (2010-07-12 23:24) [177]

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

Не надо тебе это. Seek вполне достаточно.


 
Виталий ©   (2010-07-12 23:26) [178]


> Нет. Просто пиши длину строки вместо указателя.

Как вместо указателя на строку в структуру записать длину строки?

> Seek вполне достаточно.

а вот с проблемой добавить/удалить записи и их размером все сложнее..


 
Anatoly Podgoretsky ©   (2010-07-12 23:27) [179]

> Sha  (12.07.2010 23:10:49)  [169]

Вот в список неоложных дел пусть включит и порты завершения.


 
Anatoly Podgoretsky ©   (2010-07-12 23:31) [180]

> Виталий  (12.07.2010 23:14:51)  [171]

С нами придется, если хочешь нервы сохранить


 
Anatoly Podgoretsky ©   (2010-07-12 23:31) [181]

> Юрий Зотов  (12.07.2010 23:10:50)  [170]

Если убрать динамическое выделение памяти, то будет только лучше и одни tr
finally уйдет.


 
Виталий ©   (2010-07-12 23:36) [182]


> С нами придется, если хочешь нервы сохранить

:)
А если серьезно - дайте совет, куда копать в сторону организации быстрого доступа к данным? Я думаю, это второй шаг.


 
Sha ©   (2010-07-12 23:37) [183]

> Как вместо указателя на строку в структуру записать длину строки?

Move(person, person2, size);
integer(person.FirstName):=Length(person.FirstName);
....
Move(person2, person, size);
FillChar(person2, size, 0);


> Вот в список неоложных дел пусть включит и порты завершения.

))


 
Юрий Зотов ©   (2010-07-12 23:37) [184]

> Виталий ©   (12.07.10 23:26) [178]
> Как вместо указателя на строку в структуру записать длину строки?

Либо приведением типа, либо вариантным объявлением записи:

type
 PFriend = ^TFriend;
 TFriend = record
   case boolean of
     True: (
       FirstName: AnsiString;
       LastName: AnsiString;
       BirthDate: TDate;
       Phone: AnsiString);
     False: (
       FirstLen: integer;
       LastLen: integer;
       Dummy: TDate;
       PhoneLen: integer);
 end;


 
Sha ©   (2010-07-12 23:41) [185]

> А если серьезно - дайте совет, куда копать в сторону организации быстрого доступа к данным?

А не надо было проскакивать типизированные файлы.
Мож чего бы на ум и пришло.


 
Виталий ©   (2010-07-12 23:45) [186]


> Move(person, person2, size);
> integer(person.FirstName):=Length(person.FirstName);
> ....
> Move(person2, person, size);
> FillChar(person2, size, 0);

При сохранении, как я понимаю, копируем данные во временную запись и с приведением типов записываем длину.
При загрузке - копируем назад и заполняем временную запись нулями - а это-то зачем? И таки таскаем за собой глобальную переменную!


 
Виталий ©   (2010-07-12 23:46) [187]


> А не надо было проскакивать типизированные файлы.
> Мож чего бы на ум и пришло.

А в типизированый файл я AnsiString не запишу нормально!


 
Юрий Зотов ©   (2010-07-12 23:47) [188]

> Виталий ©   (12.07.10 23:36) [182]

> куда копать в сторону организации быстрого доступа к данным?
> Я думаю, это второй шаг.

Правильно думаете. А копать в сторону Seek, конечно. Но тогда перед каждым блоком нужно писать его размер. Под блоком здесь подразумевается сама структура + 3 ее строки. То есть, если длины строк писать в самой структуре, то размер блока будет равен
SizeOf(TFriend) + Length(FirstName) + Length(LatsName) + Length(Phone)

Тогда, чтобы быстро выйти на N-й блок, в цикле делаем так:
читаем длину блока
перемещаемся на эту длину


 
Виталий ©   (2010-07-12 23:47) [189]

Там-то я, зная точный размер структуры, легко перейду к нужной с помощью Seek.


 
Sha ©   (2010-07-12 23:47) [190]

Ниасилил, значит.


 
Виталий ©   (2010-07-12 23:50) [191]


> Ниасилил, значит.

что "ниасилил"-то? Какой важный момент я упускаю?


 
Юрий Зотов ©   (2010-07-12 23:51) [192]

Во всяком случае, уже можно делать резюме: тема записи и чтения произвольных структур данных таки раскрыта.

Причем очень быстро и практически самостоятельно - поэтому непонятно, откуда взялись первоначальные проблемы.


 
Виталий ©   (2010-07-12 23:55) [193]


> откуда взялись первоначальные проблемы

До них еще дойду. Они-то не столько с этим связаны, сколько с правильным пониманием.


 
Юрий Зотов ©   (2010-07-12 23:55) [194]

> Виталий

Как насчет двух файлов? Первый - типизированный, второй - нет.
Второй хранит сами блоки данных, первый - их смещения во втором.

Тогда на любой блок данных выходим за два Seek.


 
Виталий ©   (2010-07-12 23:58) [195]


> Как насчет двух файлов? Первый - типизированный, второй
> - нет.

Мне кажется, "настоящие" базы данных не "расходуют" файлы в таком количестве. Хотя - кто их знает, как они реализованы.


 
Sha ©   (2010-07-13 00:01) [196]

> что "ниасилил"-то?

В целом полет нормальный.

> Какой важный момент я упускаю?

Например, на диске данных хранятся в секторах одного типа размером 512 байт.
И это не мешает тебе туда писать достаточно длинные строки.

> А в типизированый файл я AnsiString не запишу нормально!

Нет ли тут противоречия?


 
Виталий ©   (2010-07-13 00:04) [197]


> Нет ли тут противоречия?

Вы предлагаете ограниченную длину строки некоторым все же весьма небольшим значением. А если я хочу записать значение в пару мегабайт (заметку, например)? Причем одна заметка будет на 100 кб, а другая - на 2 мб?


 
Sha ©   (2010-07-13 00:05) [198]

> Вы предлагаете ограниченную длину строки

Где?


 
Виталий ©   (2010-07-13 00:06) [199]


> Например, на диске данных хранятся в секторах одного типа
> размером 512 байт.
> И это не мешает тебе туда писать достаточно длинные строки.
>

Или я чего-то не понимаю.


 
Sha ©   (2010-07-13 00:06) [200]

Или



Страницы: 1 2 3 4 5 6 7 8 9 
10 11 12 вся ветка

Форум: "Прочее";
Текущий архив: 2010.11.07;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.82 MB
Время: 0.063 c
6-1229185383
ASMiD
2008-12-13 19:23
2010.11.07
компонент для чтения с FTP сервера для Delphi7


2-1281957561
mm0
2010-08-16 15:19
2010.11.07
MemoryStream в потоке


15-1280325567
sniknik
2010-07-28 17:59
2010.11.07
Проверьте пожалуйста, если у вас больше чем один домен...


2-1281765808
Fr
2010-08-14 10:03
2010.11.07
Ping хоста


2-1281621980
DROWSY
2010-08-12 18:06
2010.11.07
Рабочие наборы данных.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский