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

Вниз

Освобождение ресурса в finally   Найти похожие ветки 

 
{RASkov} ©   (2008-04-27 09:52) [280]

> и постоянно поподается [1] схема...

Ну т.е. в [1] не схема, а уже код.... хорошо, схему я в [265] "зарисовал"...


 
Palladin ©   (2008-04-27 09:58) [281]


>{RASkov} ©(27.04.08 09:50) [279]

да я верю, мне интересно посмотреть на такое как в Loginov Dmitry ©(27.04.08 00:42) [267]


 
{RASkov} ©   (2008-04-27 10:01) [282]

> [281] Palladin ©   (27.04.08 09:58)
> да я верю,

А это и не тебе было :) Сорри)


 
Loginov Dmitry ©   (2008-04-27 10:03) [283]

> тебе доказать свое утверждение очень просто. указать конкретный
> модуль и либо конкретный класс и метод, либо процедуру.


раз это нужно, то с радостью все укажу! (для Delphi7, как было сказано выше)

1) Forms: TCustomForm.Print

FormImage := GetFormImage; // Создание объекта
Canvas.Lock; // захват ресурса
try
  .........
finally
  Canvas.Unlock; // Освобождение ресурса
  FormImage.Free; // Уничтожение объекта
end;


2) Forms: TCustomForm.ShowModal

В одном finally выполняется множество действий

3) Forms: TApplication.MessageBox

Не знаю, как это следует расценивать...


 finally
   if MBMonitor <> AppMonitor then
     SetWindowPos(Handle, 0,
       Rect.Left + ((Rect.Right - Rect.Left) div 2),
       Rect.Top + ((Rect.Bottom - Rect.Top) div 2),
       0, 0, SWP_NOACTIVATE or SWP_NOREDRAW or SWP_NOSIZE or SWP_NOZORDER);
   EnableTaskWindows(WindowList);
   SetActiveWindow(ActiveWindow);
   RestoreFocusState(FocusState);
 end;


4) Classes: TReader.ReadVariant, TWriter.WriteVariant


InnerStream := nil;
OuterStream := TMemoryStream.Create;
try
 InnerStream := TMemoryStream.Create;
 ..................
finally
 InnerStream.Free;
 OuterStream.Free;
end;


5) Graphics: WriteIcon()


MonoInfo := nil;
MonoBits := nil;
ColorInfo := nil;
ColorBits := nil;
try
 MonoInfo := AllocMem(MonoInfoSize);
 MonoBits := AllocMem(MonoBitsSize);
 ColorInfo := AllocMem(ColorInfoSize);
 ColorBits := AllocMem(ColorBitsSize);
 ...........................
finally
 FreeMem(ColorInfo, ColorInfoSize);
 FreeMem(ColorBits, ColorBitsSize);
 FreeMem(MonoInfo, MonoInfoSize);
 FreeMem(MonoBits, MonoBitsSize);
end;


Кстати, в модуле Controls мне не удалось найти ничего подозрительного. Там для каждого ресурса - свой try..finally, видимо, чтобы подобных споров не было ;)

В других модулях не смотрел. Достаточно и того, что я привел.


 
{RASkov} ©   (2008-04-27 10:14) [284]

> [283] Loginov Dmitry ©   (27.04.08 10:03)

А не кажется ли, что нашел иголку? ;) Даже пробежавшись по указаннум модулям >90% схема с одним объектом/ресурсрм...


 
Loginov Dmitry ©   (2008-04-27 10:23) [285]

> А не кажется ли, что нашел иголку?


Это не важно. Важно, что все-таки нашел. А поэтому фраза "Ты врешь" тут совершенно не к месту.


 
Leonid Troyanovsky ©   (2008-04-27 10:28) [286]


> {RASkov} ©   (27.04.08 10:14) [284]

> А не кажется ли, что нашел иголку? ;)

Даже меньше.
Из приведенных примеров лишь 4 бросает тень.
Но, как мы уже знаем, в борланд попадают и двоешники.
Что касается 5, то там надо было объявить структуру,
объединяющую все эти Mono-Color. Т.е., это на троечку.

--
Regards, LVT.


 
{RASkov} ©   (2008-04-27 10:31) [287]

> [285] Loginov Dmitry ©   (27.04.08 10:23)
> А поэтому фраза "Ты врешь" тут совершенно не к месту.

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


 
Leonid Troyanovsky ©   (2008-04-27 10:34) [288]


> Loginov Dmitry ©   (27.04.08 10:23) [285]

> Это не важно. Важно, что все-таки нашел

Мне когда-то даже хотелось создать зал борландовской славы,
но, к сожалению, руки не дошли. А так 4 - вполне достоен.

--
Regards, LVT.


 
Loginov Dmitry ©   (2008-04-27 10:48) [289]

А интересно, следующий код тоже дилетанский?


ADataBase := TDataBase.Create(nil);
AQuery1 := TQuery.Create(ADataBase);
AQuery2 := TQuery.Create(ADataBase);
AQuery3 := TQuery.Create(ADataBase);
try
 ................................
finally
 ADataBase.Free;
end;


 
Palladin ©   (2008-04-27 10:56) [290]

да, причем очень сильно.


 
Palladin ©   (2008-04-27 10:57) [291]

за такое, пожизненный эцих с гвоздями.


 
Loginov Dmitry ©   (2008-04-27 11:04) [292]

> за такое, пожизненный эцих с гвоздями.


а гвозди-то за что? За TQuery? ;)


 
Anatoly Podgoretsky ©   (2008-04-27 11:22) [293]

Потому что это не код, а целенаправленая диверсия.


 
Loginov Dmitry ©   (2008-04-27 11:30) [294]

> Потому что это не код, а целенаправленая диверсия.


Анатолий, объясните Вы хоть, в чем тут заключается диверсия? Почему целенаправленная?
К каким потенциальным проблемам может привести подобный код?


 
Восхищенный   (2008-04-27 11:53) [295]

> Loginov Dmitry ©   (27.04.08 11:30) [294]

Объясняю. Этот код - супердилетантский. Если на 2, 3 или 4 строке возникнет исключение, DataBase повиснет в памяти вместе с теми Query, которые успели создаться.

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

Сравни:

ADataBase := TDataBase.Create(nil);
try
 AQuery1 := TQuery.Create(ADataBase);
 AQuery2 := TQuery.Create(ADataBase);
 AQuery3 := TQuery.Create(ADataBase);
 ................................
finally
 ADataBase.Free;
end;

Вроде бы, тот же самый код - но без риска утечки памяти.


 
Anatoly Podgoretsky ©   (2008-04-27 11:57) [296]

> Loginov Dmitry  (27.04.2008 11:30:54)  [294]

К простым, в случае ошибки, теряем от одного до дву Query и сам ADataBase
А вего то переместить try на три строки выше.


 
Loginov Dmitry ©   (2008-04-27 12:09) [297]

> Профи же, наученные горьким опытом, на "авось" никогда не
> рассчитывают, даже если вероятность ошибки 10e-6.


"Профи же, наученные горьким опытом" - такие вообще существуют, или это лишь теория?

Как вообще может произойти ошибка в таких безобидных конструкторах, как
TDataBase.Create, TQuery.Create, TList.Create, TStringList.Create, TMemoryStream.Create
если ее намеренно не спровоцировать?

Таким же макаром и в деструкторе может произойти ошибка, а в случае TDataBase и TQuery ошибка в деструкторе даже более вероятна, чем в конструкторе, тогда опять же есть риск утечки памяти.

10e-6 - очень большая цифра, означающая, что если в цикле миллион раз вызвать данный код, то в одном из конструкторов хотябы 1 раз произойдет AV.


 
Palladin ©   (2008-04-27 12:29) [298]


>Как вообще может произойти ошибка в таких безобидных конструкторах, как
TDataBase.Create, TQuery.Create, TList.Create, TStringList.Create, TMemoryStream.Create

да очень просто, не нужно рассуждать так линейно. например рядом крутящийся поток пишущий в неверную область памяти, программа какого нибудь "кул хацкера" делающая WriteProcessMemory. все это угрожает стабильности приложения.

идеально стабильное - не существует, но приблизить его к идеалу мы можем. чем и занимаемся, грамотно выстраивая try finally и стараясь спасти ситуацию. приложению ведь еще и дальше работать.

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


 
Palladin ©   (2008-04-27 12:35) [299]


>конструктор для нас темная лошадка.

извиняюсь, не договорил,

темная лошадка. сегодня он безобидный, завтра преопаснейший. и мы имеем огромную кучу проблем и мемликов.


 
{RASkov} ©   (2008-04-27 12:37) [300]

:)
Аринушка наверное в трансе)


 
Anatoly Podgoretsky ©   (2008-04-27 12:52) [301]

> {RASkov}  (27.04.2008 12:37:00)  [300]

В трансе наверно Дмитрий глаза открыли - откуда дети берутся.


 
Loginov Dmitry ©   (2008-04-27 12:54) [302]

> например рядом крутящийся поток пишущий в неверную область
> памяти


Очень часто это приводит к краху программы, и мало вероятности, что try..finally от этого сможет спасти. К чему спасать, если программа дальше не сможет работать корректно? Запись в неверную область памяти - это программная ошибка, которую исправлять надо.


> стараясь спасти ситуацию. приложению ведь еще и дальше работать.


Кратко и убедительно!


> [299] Palladin ©   (27.04.08 12:35)
>
> >конструктор для нас темная лошадка.
>
> извиняюсь, не договорил,
>
> темная лошадка. сегодня он безобидный, завтра преопаснейший.
> и мы имеем огромную кучу проблем и мемликов.


Если сегодя какой-нибудь TList.Create безопасный, а завтра - преопаснейший, то какой толк от всех этих try..finally, если программа работать не сможет? ;) Хотя то, что при этом не будет никаких утечек памяти - это конечно круто!

Хотя в принципе и такое возможно. Действительно, если класс не такой примитивный, как TList (например, тот же TDataBase / TQuery), то еще неизвестно, как конструктор себя поведет, если на компьютере не инсталлирован необходимый для его работы софт, а приложение должно работать в любом случае...

Ладно! Основную идею понял! Убедили! Спасибо!


 
Восхищенный   (2008-04-27 13:06) [303]

> Loginov Dmitry ©   (27.04.08 12:09) [297]

> "Профи же, наученные горьким опытом" - такие вообще существуют

Существуют, и очень много. Здесь они тоже есть, и тоже немало. Ты их тоже видишь, просто пока не понимаешь их действительного уровня.

> Как вообще может произойти ошибка в таких безобидных конструкторах,
> как TDataBase.Create, TQuery.Create, TList.Create, TStringList.Create,
> TMemoryStream.Create если ее намеренно не спровоцировать?

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

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

В твоем примере любой профи, даже вдрызг пьяный, автоматически и не задумываясь написал бы try на 3 строки выше. Автопилот срабатывает.


 
Loginov Dmitry ©   (2008-04-27 13:24) [304]

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


Ну ладно. Опустили Вы меня (и не только :), аж не по себе стало!
Я даже по такому случаю статейку ту перепишу, чтоб не позориться :)


 
Игорь Шевченко ©   (2008-04-27 13:31) [305]


> Я даже по такому случаю статейку ту перепишу, чтоб не позориться
> :)


Не писал бы ты...Зачем нужны клоны трудов Архангельского ?


 
Экс-Оригинал   (2008-04-27 13:54) [306]

Если говорить о конкретных случаях при создании нескольких объектов, то, зная, как они должны работать, как работают конструкторы, возможные исключения, - не вижу никакого доказательства невозможности конструкции с дополнительными присваиваниями.

Хотелось бы поверить, что это неправильно ВО ВСЕХ случаях, но не могу принять на веру, так как не вижу смысла слепо верить авторитетам, тем более слушать анонимные безапелляционные высказывания.

Пока из всего вышесказанного видно, что в некоторых случаях (если не знать внутреннй реализации до тонкостей) конструкция с дополнительным присваиванием может быть неустойчивой к исключениям. но это только лишь В НЕКОТОРЫХ случаях.

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

Это тоже самое, что сказать - вот в этом случае GOTO плохо. Значит, плохо везде.


 
Экс-Оригинал   (2008-04-27 13:58) [307]


> Loginov Dmitry ©   (27.04.08 13:24) [304]
> Опустили Вы меня (и не только :),
>  аж не по себе стало!Я даже по такому случаю статейку ту
> перепишу, чтоб не позориться :)


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

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


 
Loginov Dmitry ©   (2008-04-27 14:07) [308]

> Не писал бы ты...Зачем нужны клоны трудов Архангельского
> ?


По хорошему удалить ее следует. Но жалко :(


 
Loginov Dmitry ©   (2008-04-27 14:31) [309]

> Зачем нужны клоны трудов Архангельского


Кстати, Архангельский в одном из источников некорректно описывал спицифику работы с try..finally, а из-за этого я долгое время пренебрегал использованием данного оператора, и извращался с try..except. А статья была написана с целью помочь начинающему в освоении и понимании try..finally, поскольку достаточные объяснения приводятся далеко не каждым автором. Статья свою работу, считаю, делает, так зачем ее удалять? Нужно ее просто доработать с учетом всех накопленных с того момента знаний.


 
Восхищенный   (2008-04-27 14:42) [310]

> Loginov Dmitry ©   (27.04.08 14:31) [309]

> А статья была написана с целью помочь начинающему в освоении и
> понимании try..finally,

И, желая помочь начинающему в понимании try..finally, ты пишешь вот такой страшный пример (кстати, четко показывающий, что ты и сам толком не понимаешь того, о чем пишешь). А этот бедняга начинающий, не в состоянии даже понять, что пример страшный, и думает, что так и надо делать.

Выглядишь ты при этом довольно смешно, но не это главное. Главное вот что - ты понимаешь, что совершаешь почти преступление?


 
Игорь Шевченко ©   (2008-04-27 14:57) [311]

Расстрелять и дело с концом


 
Экс-Оригинал   (2008-04-27 15:39) [312]


> Leonid Troyanovsky ©   (27.04.08 10:28) [286]


По поводу кода 4:
Delphi 6:
 function ReadCustomVariant: Variant;
 var
   OuterStream, InnerStream: TMemoryStream;
   OuterReader: TReader;
   StreamSize: Integer;
   CustomType: TCustomVariantType;
   CustomTypeClassName: string;
   VarStreamer: IVarStreamable;
 begin
   CheckValue(vaBinary);
   OuterStream := TMemoryStream.Create;
   InnerStream := TMemoryStream.Create;
   try
     Read(StreamSize, SizeOf(StreamSize));
     OuterStream.Size := StreamSize;
     Read(OuterStream.Memory^, StreamSize);

     OuterReader := TReader.Create(OuterStream, 1024);
     try
       CustomTypeClassName := OuterReader.ReadString;
       OuterReader.Read(StreamSize, SizeOf(StreamSize));
       InnerStream.Size := StreamSize;
       OuterReader.Read(InnerStream.Memory^, StreamSize);

       if not FindCustomVariantType(CustomTypeClassName, CustomType) or
          not Supports(TObject(CustomType), IVarStreamable, VarStreamer) then
         raise EReadError.CreateRes(@SReadError);
       TVarData(Result).VType := CustomType.VarType;
       VarStreamer.StreamIn(TVarData(Result), InnerStream);
     finally
       OuterReader.Free;
     end;
   finally
     InnerStream.Free;
     OuterStream.Free;
   end;
 end;


BDS2006:

 function ReadCustomVariant: Variant;
 var
   OuterStream, InnerStream: TMemoryStream;
   OuterReader: TReader;
   StreamSize: Integer;
   CustomType: TCustomVariantType;
   CustomTypeClassName: string;
   VarStreamer: IVarStreamable;
 begin
   CheckValue(vaBinary);

   InnerStream := nil;
   OuterStream := TMemoryStream.Create;
   try
     InnerStream := TMemoryStream.Create;

     Read(StreamSize, SizeOf(StreamSize));
     OuterStream.Size := StreamSize;
     Read(OuterStream.Memory^, StreamSize);

     OuterReader := TReader.Create(OuterStream, 1024);
     try
       CustomTypeClassName := OuterReader.ReadString;
       OuterReader.Read(StreamSize, SizeOf(StreamSize));
       InnerStream.Size := StreamSize;
       OuterReader.Read(InnerStream.Memory^, StreamSize);

       if not FindCustomVariantType(CustomTypeClassName, CustomType) or
          not Supports(CustomType, IVarStreamable, VarStreamer) then
         raise EReadError.CreateRes(@SReadError);
       TVarData(Result).VType := CustomType.VarType;
       VarStreamer.StreamIn(TVarData(Result), InnerStream);
     finally
       OuterReader.Free;
     end;
   finally
     InnerStream.Free;
     OuterStream.Free;
   end;
 end;


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

Во втором случае всё наглядно.


 
Loginov Dmitry ©   (2008-04-27 23:41) [313]

> И, желая помочь начинающему в понимании try..finally, ты
> пишешь вот такой страшный пример (кстати, четко показывающий,
> что ты и сам толком не понимаешь того, о чем пишешь). А
> этот бедняга начинающий, не в состоянии даже понять, что
> пример страшный, и думает, что так и надо делать.
>
> Выглядишь ты при этом довольно смешно, но не это главное.
> Главное вот что - ты понимаешь, что совершаешь почти преступление?


Признаю все свои ошибки. И по поводу статьи, и по поводу примеров и т.д. и т.п.
Если разобраться, то в VCL (начиная с Delphi7) действительно нет ни одного участка, в котором исключение в конструкторе привело бы к утечке памяти. Видимо, не просто так они там все подправили. Наверно, от них требуют (или требовали) придерживаться существующего стандарта, наказывая за произвол :) Либо же на самом деле вероятность ошибки в конструкторе - ненулевая. Ну так или, VCL как и всегда является примером для подражания :)

Статью переписал (ссылка в [33]). Заменил весь контент, идущий, после перевода хэлпа, на более правдоподобную информацию (в основном копи-пастом из этой ветки :)
Прошу профи оценить правдоподобность изложенного в ней материала. Если по Вашему мнению все правильно, то оставлю как есть, иначе же все что необходимо - исправлю. Главное, чтобы она приносила, как минимум, больше пользы, чем вреда :)


 
Игорь Шевченко ©   (2008-04-28 00:05) [314]

"В секции finally должна выполняться обработка любых возникающих в ней исключений, в противном случае будет невозможно выполнить обработку других исключений. "

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

try
 ....
finally
 try
   ...
 except
   ...
 end;
end;

"Не следует использовать уровень вложенности операторов try..finally больше 4-х, т.к. это снижает читабельность кода"

а 4 - это эмпирическая константа или как ?

"Код конструктора выглядит примерно так:

constructor TSomeClass.Create;
begin
 try
  { Ваш код конструктора }
 except
   Destroy;
 end;
end;

"

точнее, так:
 try
  { Ваш код конструктора }
 except
   Destroy;
   raise;
 end;


"Правильно разработанный код деструктора теоретически не должен ни при каких обстоятельствах провоцировать возникновение исключения."

почему не должен - оно просто передастся наверх и вся радость.

"Теоретически исключение может возникнуть при любой операции, требующей выделения участка памяти ненулевой длины. Вызов любого конструктора приводит к выделению памяти, необходимой для хранения полей создаваемого объекта"

не любого.

"Если при выделении памяти функцией AllocMem() произойдет исключение, FreeMem() освободит память только для ненулевых указателей"

что, FreeMem проверяет на nil ?

"In Delphi code, FreeMem destroys the variable referenced by P and returns its memory to the heap. If P does not point to memory in the heap, a runtime error occurs. If P points to a structure that includes long strings, variants, dynamic arrays, or interfaces, call Finalize before calling Freemem .

P is a variable of any pointer type previously assigned by the GetMem procedure.

Size specifies the size in bytes of the dynamic variable to dispose of; if specified, it must be exactly the number of bytes previously allocated to that variable by GetMem .
After calling FreeMem, the value of P is undefined.
Note: It is preferable to use the New and Dispose procedures rather than GetMem and FreeMem. When using New and Dispose , there is no need to explicitly call Finalize ."


Говорил же - не пиши.


 
Anatoly Podgoretsky ©   (2008-04-28 00:21) [315]

> Игорь Шевченко  (28.04.2008 00:05:14)  [314]

"Код конструктора выглядит примерно так:

constructor TSomeClass.Create;
begin
try
 { Ваш код конструктора }
except
  Destroy;
end;
end;

"

точнее, так:
try
 { Ваш код конструктора }
except
  Destroy;
  raise;
end;

-----------

это тоже смущение для неокрепших душ, а вдруг поверят? Тебе же тогда второй приз надо будет выдавать, первый Архангельскому, а вот правильный код

constructor TSomeClass.Create;
begin
  { Ваш код конструктора }
end;

destructor Destroy
begin
  Destroy;
end;


 
Anatoly Podgoretsky ©   (2008-04-28 00:24) [316]

> Anatoly Podgoretsky  (28.04.2008 00:21:15)  [315]

Ах да, для конструктора Destroy не надо делать, Destroy только для созданых в конструкторе или далее в коде объектов, и конечно без какого либо (кроме редких случаеу) Assingned, для необъектов или если рашрушение в коде, но и тогда не стоит, лучше сделать obj := nil


 
Anatoly Podgoretsky ©   (2008-04-28 00:26) [317]

> Anatoly Podgoretsky  (28.04.2008 00:24:16)  [316]

Кстати у тебя есть большое желание писать, но надо подождать (если желание не пройдет), пока уровень мастерства возрастет, а пока только вред наносишь.


 
Игорь Шевченко ©   (2008-04-28 00:29) [318]

Anatoly Podgoretsky ©   (28.04.08 00:21) [315]


> это тоже смущение для неокрепших душ, а вдруг поверят? Тебе
> же тогда второй приз надо будет выдавать, первый Архангельскому


Ага, сознаюсь, повелся.
Это код _ClassCreate выглядит так, с try..except


 
Экс-Оригинал   (2008-04-28 00:47) [319]


> Говорил же - не пиши.


Жалко, что-ли? -(


 
Экс-Оригинал   (2008-04-28 00:49) [320]


> Loginov Dmitry ©   (27.04.08 23:41) [313]


Если ечть желание писать, то обязательно договариваться с рецензентами - пусть читают, потом апрвить, опять на рецензию отдавать...
И только после этого - выкладывать в общество...



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

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

Наверх





Память: 1.1 MB
Время: 0.232 c
2-1210771941
Alex7
2008-05-14 17:32
2008.06.08
ADODataSet Как сделать сортировку по агрегатному полю?


15-1209107695
Slider007
2008-04-25 11:14
2008.06.08
С днем рождения ! 25 апреля 2008 пятница


2-1211026843
Ultimate
2008-05-17 16:20
2008.06.08
Загрузка определенной строки из файла


15-1209129515
snake-as
2008-04-25 17:18
2008.06.08
Работа с Exel


2-1211116922
Johnny
2008-05-18 17:22
2008.06.08
Добавить поле в Access





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский