Delphi переписать строку в текстовом файле

Обновлено: 05.07.2024

Текстовые файлы

Итак у всех потомков класса TStrings (TStringList, memo.Lines и т.п. ) есть методы записи и чтения в файл - SaveToFile, LoadFromFile. Преимущество - простота использования и довольно высокая скорость, недостаток - читать и писать файл можно только целиком.

1. Загрузка текста из файла в Memo:

2. Сохранение в файл:

3. А вот так можно прочитать весь файл в строку:

Паскалевский метод доступа

Для более тонких операций над текстовыми файлами прийдется освоить очень древний паскалевский способ.

Итак, для доступа к текстовым файлам используется переменная типа TextFile. До сих пор не совсем понимаю что это такое физически - что-то типа "внутреннего" паскалевского Handle на файл.

Итак чтобы ассоциировать файл на диске с переменной надо проделать следующие опрерации:

1) Определяем файловую переменную:

2) Ассоциируем ее:

3) Теперь надо этот файл открыть, есть 3 варианта:

  1. файла нет или он должен быть перезаписан, открытие для записи: Rewrite(f)
  2. файл есть и его надо открыть для чтения (с первой строки): Reset(f)
  3. файл есть и его надо открыть для дописования строк в конец: Append(f)

Как видите не хватает очень полезных функций таких как открытия файла для чтения с произвольной строки и для записи в файл произвольной строки. Но надо учесть, что так как длины строк разные, не существует никакого способа узнать физическое место начала например 1000 строки, не прочитав всю тысячу строк. Для записи ситуация еще сложнее - вставить строку означает перезаписать всю информацию после этой строки заново. Таким образом варианты только следующие:

  • Перезаписать весть файл
  • Читать с первой строки
  • Дописать что-то в конец
  • Читать и писать файл целиком (см. выше работу через TStrings)

В конце работы открытый файл нужно закрыть:

Теперь пусть у нас есть строковая переменная s для чтения строки из файла

Чтение предварительно открытого файла:

ReadLn(f, s) - будет прочитанна текущая строка и позиция чтения переведена на следующую позицию.

А как прочитать весь файл?

Хорошо, а если файл несколько метров есть ли способ поставить какой-нибудь ProgressBar или Gauge чтобы показывал сколько считанно? Есть, но не совсем прямой - не забыли, сколько строк в файле заранее мы не знаем, узнать можно только прочитав его весь, но показометер мы все-таки сделаем:

Теперь комментарии к коду.

  1. Функию GetFileSize я рсссмотрю после, она немного по другому подходит к чтению файла (кстати я знаю еще по крайней мере 3 способа ее реализации, поэтому не нужно указывать что это можно сделать легче, быстрее или просто по другому - просто давайте разберем это позже)
  2. Переменная i - все время указывает на количество байт которое мы считали - мы определяем длину каждой строки и прибавляем 2 (символы конца строки). Зная длину файла в байтах и сколько байт прочитано можно оценить и прогресс, но
  3. Если ставить изменение прогресса после каждой строки, то это очень сильно тормознет процесс. Поэтому вводим переменную j и обновляем прогресс например 1 раз на 1000 прочитанных строк
  4. Переменная Canceled - глобальная переменная. Поставьте на форму кнопку, в обработчике нажатия поставьте Canceled:=True; и нажатие кнопки прервет чтение файла.

Теперь как писать в текстовый файл:

Запись целой строки:

Запись кусочка строки(те следующая операция записи будет произведена в ту же строку):

Если переменная s содержит больше 255 символов (т.е. является длинной строкой), то таким способом ни фига не запишится, в файл вместо строки попадут 4 байта указателя на нее. Надо делать так:

Работа через WinAPI

Раздел написан Podval (примеры к сожалению на С++)

Любителям WinAPI посвящается. Функции FileOpen, FileSeek, FileRead. Возьмем форму, положим на нее кнопку, грид и Опен диалог бокс. Это для Билдера, но какая нам в данном случае разница?

Потренируемся еще. Функции FileExists, RenameFile, FileCreate, FileWrite, FileClose. Бросим на форму Save dialog box.

(с) Оба примера взяты из хелпа по Borland C++ Builder 5.

Первоисточник тот же.

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

В этом примере идет поиск в текущем каталоге и каталоге Windows

В дополнение к Дате/Времени

Для конвертации возвращаемого значения в TDateTime:

Типизированные файлы

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

Объявляем файл байтов:

Ассоциируем файловую переменную с физическим файлом:

Теперь мы можем либо перезаписать/создать файл:

Либо открыть существующий для чтения и записи:

Обратите внимание, что функция Reset хотя и имеет такой же формат как и для текстовых файлов, но открытый ей файл можно и читать и писать, в отличие от текстовых.

Теперь функции работы с файлом:

Все эти функции не работают с файлами большими 2 Gb.

После работы файл надо закрыть:

Приведенные выше механизмы будут работать с любым файлом, так как любой файл можно считать файлом байтов. Теперь где это можно использовать? В принципе везде, но в подавляющем большинстве случаев это будет очень неудобно, ведь скорость считывания при чтении по байтам будет на порядки более низкой чем другими способами. Однако в некоторых случаях этот способ может быть очень полезен. Например в программе вам надо заменить 100й байт файла на другой, или прочитать 100й байт файла, например во всяких читерских программах, при взломе и т.п. Здесь такой доступ будет весьма удобен. Гораздо более интересным представляется дальнейшее развитие технологии типизированных файлов (их еще лет 15 назад называли "Файлы прямого доступа"). Представим себе, что файл состоит не из байт а из более сложных структур. Например мы имеем некоторую информацию в виде:

Обратите внимание, что все элементы записи точно типизированны, нет ни длинных строк, ни открытых массивов, ни объектов, другими словами, заранее точно известно сколько именно байт будет занимать переменная этого типа. Объявим переменную этого типа:

и файл этого типа:

Теперь мы можем читать и писать сразу целую структуру, абсолютно так же как и если бы это был один байт:

Все остальные функции приведенные в предыдущей статье будут работать так же, только одно отличие - Seek и Size оперируют не с количеством байт, а с количеством записей.

Нетипизированные файлы

Идем дальше. Есть такое понятие как нетипизированный файл. Это такой файл который содержит разнородные элементы. Например файл EXE - вначале он имеет заголовок, затем двоичный код, в конце какие-то ресурсы. Все части файла имеют разную длину и разную структуру. Тут уже обратится к произвольному элементу сложно, обычно надо вначале узнать где этот элемент находится, подчас это записано в предыдущем куске информации. Работа с такими файлами достаточно сложна и требует вручную разработки алгоритмов его чтения, но в связи гибкостью структуры и компактностью такие файлы составляют большинство. Для работы с нетипизированными файлами используют процедуры BlockRead и BlockWrite, которые позволяют читать/писать произвольное количество байт. Привожу пример пользования этими функциями из справки по Дельфи:

Этот код копирует из одного файла в другой. Замечания по поводу этого метода работы с файлами - плюсы - очень высокая скорость, особенно если размер буффера увеличить до 64kb-512kb, что позволит считывать файл достаточно большими кусками, чтобы обеспечить отсутствие простоев винчестера, к тому же обеспечивается очень высокая гибкость в работе. Минусы - сложность разработки, необходимость вручную писать все детали механизма чтения/записи и интерпретации данных.

Пожалуй на этом можно было бы и завершить описание работы с файлами средствами Паскаля и файловых переменных, но заглянув в Help Дельфей я обнаружил еще несколько функций достойных упоминания.

Файловые потоки

Теперь разберем возможности работы потомка TStream - TFileStream - файловый поток. Этот класс был специально введен для работы с файлами. Для работы с файловым потоком Вам надо записать в Uses модули classes, Sysutils (classes - включает в себя собственно определение класса, Sysutils - некоторые константы необходимые для работы).

Вот пример записи/перезаписи файла:

Теперь небольшой разбор:

TFileStream.create - конструктор класса, его вызов требует указания имени файла и опций его открытия, следующие опции определены:

Теперь метод Write - этим методом в файл пишется любая информация из буфера любого типа, Вам надо указать только буффер и количество записываемых байтов. В данном случае используется переменная типа String в качестве буффера, но так как для длинных строк она представляет собой лишь указатель, то конструкция "pointer(s)^" заставляет обращаться именно к ее содержимому.

А вот этот код демонстрирует чтение файла с использованием файлового потока:

И пояснения к коду:

  1. Никаких проверок длину файла и его наличие здесь не делается - это демонстрационный код, а не готовая процедура чтения.
  2. Файл мы считываем в буффер типа PChar (с тем же успехом можно использовать массив или любой другой контейнер). Для тех кто не помнит - процедуры GetMem(p, 255) и FreeMem(p) - распределение памяти для строки и освобождение памяти.
  3. Метод потока Seek позволяет установить текущую позицию считывания/записи файла. Первый параметер - номер байта, второй - это от чего считать этот байт (у нас считать от начала файла), возможны варианты:
    • soFromBeginning - от начала файла
    • soFromCurrent - от текущей позиции считывания
    • soFromEnd - от конца файла (в этом случае номер байта должен быть отрицательным или равным нулю)
  4. Собственно считывание из потока осуществляется методом read, в котором указывается в качестве параметров буфер в который мы читаем и желаемое количество байт для чтения. Метод read является функцией, которая возвращает количество байт реально прочитанных из потока.

Заканчивая о файловых потоках хочу упомянуть о методе

CopyFrom который позволяет перекачивать информацию из одного потока в другой и о свойствах:

Size - размер файла
Position - текущая позиция чтения/записи потока

Работа с файловыми потоками весьма быстра, этот класс, являсь классом VCL, в то же время базируется на низкоуровневых функциях Windows, что обеспечивает очень высокую скорость работы и стабильность операций. К тому же многие компоненты и классы VCL поддерживаю прямое чтение и запись с файловыми потоками, что занчительно упрощает работу - например TStringList, TBlobField, TMemoField и другие.

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

Работа через Handle

Еще один способ работы с файлами - это открытие Handle на файл и работу через него. Тут есть 2 варианта - можно использовать функции Дельфи или использовать WinAPI напрямую.

При использовании функций Дельфи можно применять следующие функции:

FileOpen(FileName, fmOpenWrite or fmShareDenyNone) - функция открывает файл и возвращает целое цисло - Handle на файл. Параметры функции - имя файла и тип доступа (все типы доступа я перечислил ранее). Если файл успешно открыт то Handle должен быть положительным цислом, отрицательное число - это код ошибки.

Во всех остальных функциях используется именно значение Handle, возвращаемое этой функцией.

FileClose(Handle: Integer) - закрывает файл

FileRead(Handle: Integer; var Buffer; Count: Integer): Integer;
FileWrite(Handle: Integer; const Buffer; Count: Integer): Integer;

Эти функции для чтения/записи файла, где Buffer любая переменная достаточного размера для чтения/записи куска информации (обычно типа PChar или массив), Count-количество байт, которое Вы желаете записать/прочитать. Функции возвращают количество байт которые реально были прочитанны или записаны.

Этот тип доступа к файлам применяется весьма редко. Дело в том что он практически дублирует соответствующие функции WinAPI и к тому же обычно работает несколько медленнее, чем например потоки. И все же использование функций FileOpen и FileClose не лишено привлекательности. Наряду с тем что эти функции намного легче в использовании соответствующих функций WinAPI (можете сравнить - FileOpen имеет 2 параметра, cooтветствующая функция WinAPI - CreateFile имеет 7 параметров, большая часть из которых реально требуется лишь в ограниченном числе случаев) этот путь доступа открывает возможность прямого использования всех функций WinAPI про работе с файлами, которые требуют Handle на открытый файл.

Файловые операции

Дельфи предоставляет довольно широкие возможности по файловым операциям без использования механизмов открытия/закрытия файлов.

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

ChDir(NewCurrentPath: string); - изменяет текущий каталог (в среде Windows сие конечно не так актуально как в ДОС, но все же), прочитать же текущий каталог можно функцией GetCurrentDir, а текущий каталог для определенного драйва - GetDir.

CreateDir(const Dir: string): Boolean; - создает каталог. При этом предыдущий уровень должен присутствовать. Если вы хотите сразу создать всю вложенность каталогов используйте функцию ForceDirectories(Dir: string): Boolean; Обе функции возвращают True если каталог создан

DiskFree(Drive: Byte): Int64; - дает свободное место на диске. Параметер - номер диска 0 = текущий, 1 = A, 2 = B, и так далее

DiskSize(Drive: Byte): Int64; - размер винта. Обратите внимание на то что для результата этой и предыдущей функций абсолютно необходимо использовать переменную типа Int64, иначе макимум того что вы сможете прочитать правильно будет ограничен 2Gb

FileExists(const FileName: string) - применяется для проверки наличия файла

FileGetAttr(const FileName: string): Integer;
FileSetAttr(const FileName: string; Attr: Integer): Integer; - функции для работы с атрибутами файлов. Вот список возможных атрибутов:

RemoveDir(const Dir: string): Boolean; - удаляет папку(пустую)
DeleteFile(const FileName: string): Boolean; - удаляет файл
RenameFile(const OldName, NewName: string) - переименовывает файл

Информация о файле

Привожу пример функции которая собирает довольно большое количество информации о выбранном файле:

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

Поиск файлов

Теперь поговорим о поиске файлов. Для этой цели могут использоваться процедуры FindFirst, FindNext, FindClose, при участии переменной типа TSearchRec которая хранит информацию о текущем статусе поиска и характеристики последнего найденного файла.

Пример иллюстрирующий поиск всех файлов и каталогов в определенном каталоге:

Когда речь идет о работе программы с текстовым файлом, подразумеваются процедуры ввода данных из файла в программу или, наоборот, запись этих данных в файл программой. Для текстового файла допустима простая работа с файлом без особых дополнительных механизмов, которые применяются для работы со специализированными файлами, такими как при загрузке данных из Excel или работе программы с базой данных. Разумеется, Delphi располагает возможностями работать с файлами с использованием компонентов. Но в данной статье рассматривается механизм прямой работы с текстовым файлом без использования дополнительных компонентов.

Итак, в общем виде, работа с файлом заключается в следующих этапах:

1. подключение к файлу – связь с внешним файлом, указание режима подключения;

2. выполнение операций записи в файл или чтения из файла;

3. завершение работы с файлом.

Подключение к файлу

Для связи программы с файлом используется специальная переменная – "Файловая переменная". Объявляется она так же как и любая переменная в Delphi. Тип это переменной может быть File для типизированных (хранящих данные определенного типа) файлов, а можно указать TextFile, что будет означать тип обычного текстового файла. Объявление переменной:

В исполняемом коде программы выполняется подключение к внешнему файлу:

Команда AssignFile, выполняет связь файловой переменной с внешним файлом. Вторым параметром указывается адрес файла. Он может быть задан относительным или абсолютным. Если указать только имя файла, то программа будет пытаться обнаружить его в той же директории, где она сама и находится. Абсолютный путь указывается от корневого диска:

Использование относительной директории дает возможность не привязываться к конкретным дискам и адресам. Например:

После того как выполнено подключение, выполняется процедура, устанавливающая режим работы с файлом. В основном это режим чтения или записи. Эти режимы назначаются процедурами Reset() ( для чтения) и rewrite() (для записи):

* Для команды Rewrite() следует учитывать, что при ее выполнении, она либо создает файл, указанный в файловой переменной, либо если он уже есть перезаписывает файл заново, удаляя старый без какого-то предупреждения.

Любую из указанных команд можно использовать без команды AssignFile(). Для этого достаточно вторым параметром указать путь к файлу. Таким образом, она сразу выполнит привязку файла к файловой переменной и назначит режим работы с этим файлом:

Операции с файлами

Для чтения из файла, необходимо назначить режим чтения и использовать команду Readln(), которая будет вводить в строковую переменную по одной строке из файла. Затем с этой переменой можно выполнить необходимые действия.

Обычно для загрузки всех строк из файла используется оператор цикла. Для того, чтобы определить, что файл закончился используется функция EOF() (End Of File). Таким образом получается цикл, в котором последовательно в строковую переменную вводятся все строки файла и завершающийся после окончания фала:

Для записи, назначение режим записи в файл и командой Writeln() производится запись по строкам.

Закрытие файла

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

Примеры работы с текстовыми файлами в Delphi

Чтение в переменную одного значения из файла:

Загрузить все строки файла в компонент Memo:

Следует отметить, что для этой задачи проще воспользоваться командой самого компонента Memo LoadFromFile().

Записать строку в файл:

Записать в текстовый файл все строки из компонента Memo:

Как и для чтения из файла в Memo, так и здесь, имеется специальная команда:

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

Для "лирического" вступления нужно упомянуть компоненты Delphi, которые умеют работать с файлами. Они читают и сохраняют своё содержимое, строки типа String, в файл текстового формата. Это компоненты ListBox, ComboBox и Memo, расположенные на первой же вкладке палитры компонентов.

Каждая строка компонентов ListBox и ComboBox является объектом Items[i], а Memo - Lines[i], где i - номер строки, который отсчитывается от нуля. Добавление строк в компоненты выполняется методами Add и Insert:

Компоненты сохраняющие содержимое


begin
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
end ;

Метод Add добавляет новую строку в конец. Метод Insert имеет дополнительный параметр, указывающий, после какой строки разместить новую строку. Доступ к строкам осуществляется так:

ComboBox1.Items[0] := 'Первая строка изменилась' ;
ListBox1.Items[1] := 'Вторая строка изменилась' ;

У компонента ComboBox дополнительно есть свойство Text, где (как и у компонента Edit) находится вводимый текст:

ComboBox1.Text := ' Вводимый текст ';

На выделенную в данный момент строку компонента ComboBox указывает свойство ItemIndex типа Integer, то есть это номер выделенной строки. Следовательно, получить саму выделенную строку компонента ComboBox можно следующей конструкцией:

или, пользуясь оператором присоединения

With ComboBox1 do
S:=Items[ItemIndex];

Вот как по нажатию клавиши Enter можно заносить в этот компонент вводимую в строку информацию и удалять нажатием Escape:
Выделите на Форме ComboBox и перейдите в Инспектор объектов, на вкладку Events. Щёлкните дважды по обработчику OnKeyPress. Система Delphi создаст заготовку обработчика. Напишите:

Ну а теперь собственно о сохранении содержимого в файл. Для этого выполните команду

ListBox1.Items.SaveToFile(' Имя_файла.txt ') ;

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

ListBox1.Items.LoadFromFile(' Имя_файла.txt ') ;

Что делать, если в своей программе мы не работаем с компонентами Combobox, ListBox или Memo, а сохранять информацию нужно? Берём один из компонентов и делаем его невидимым, для этого в Инспекторе Объектов ставим в свойство Visible значение False. Функциональность его от этого не изменится!

Последний штрих - создадим программу, сохраняющую своё положение на экране в момент закрытия и там же открывающуюся. Нам нужно сохранить два параметра - значения свойств Формы Left и Top, это расстояние от левого и верхнего краёв экрана соответственно. Значения эти выражаются в пикселах и имеют тип Integer. Необходимо перевести эти числа в строку (тип String) с помощью оператора IntToStr. Итак, разместите на Форме невидимый ListBox, щёлкните по пустому месту Формы, чтобы её свйства появились в Инспекторе объектов, и перейдите на вкладку Events. Щёлкните по обработчику OnClose и в созданной заготовке напишите:

begin
ListBox1.Items.Clear;
ListBox1.Items.Add(IntToStr(Form1.Left));
ListBox1.Items.Add(IntToStr(Form1.Top));
ListBox1.Items.SaveToFile('MyFormPos.txt');
end ;

Этот обработчик сохраняет положение Формы на экране. Теперь напишем обработчик, помещающий Форму на прежнее место при старте программы. Создайте заготовку обработчика события OnCreate. Это событие происходит в момент "создания" Формы операционной системой. В этот момент и нужно присваивать ей необходимые свойства. Пишите:

begin
if FileExists('MyFormPos.txt') then
begin
ListBox1.Items.LoadFromFile('MyFormPos.txt');
Form1.Left:=StrToInt(ListBox1.Items[0]);
Form1.Top:=StrToInt(ListBox1.Items[1]);
end ;
end ;

В первой строке происходит проверка на существование файла, ведь если его не будет, произойдёт ошибка. Впрочем, программа после выдачи предупреждения откроется в том месте, где была на этапе проектирования, а при закрытии нужный файл будет воссоздан!
Затем в логических скобках begin / end содержится сам код, который будет выполнен только приналичии файла MyFormPos.txt в папке с программой, так как используется относительный путь. Можно указать конкретное местоположение, например, C:\Program Files\MyProg\MyFormPos.txt.

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

Конечно, профессиональные программы сохраняют своё положение в Реестре Windows. Но всему своё время.

Leha, добавлено 27.07.09, 09:30:54
Да. Великолепный пост. Добавил в мемориз. Mihan, добавлено 29.07.09, 08:24:43
Мда. Примерно тоже самое прочитал на севендей.ру. Уже много раз замечал. Такое ощущение, что они просто переписывают посты. Хотя. может меня и подглючивает . Автор, добавлено 29.07.09, 11:21:21
Робяты, ну никак понять не могу, почему все имена по-английски пишут!
Raven, добавлено 3.08.09, 14:49:46
Соглашусь с первым автором,и хочу сразу же задать вопрос.У меня в listbox выводится Имя а потом Номер в скобках тоесть вот так к примеру Елена(920*******) как сделать чтобы при нажатии на Елену в Edit записывался только номер Ответ, добавлено 3.08.09, 17:23:19
Можно вычислить номер символа "(" и скопировать текст от этого номера плюс один до номера символа ")" минус один. Как это делается, объяснять? Raven, добавлено 4.08.09, 11:10:38
Да объяснять=).Спасибо что ответили,я самоучка просто.Читаю книжку в данный момет библия для программиста в среде делфи,но пока ответа на свой вопрос там не нашел.Расскажите пожалуйста вы если не сложно.Заранее спасибо. Продолжаем разговор!, добавлено 4.08.09, 14:13:45
Нужно освоить работу со строками. Есть функция Pos, которая даёт позицию первого вхождения нужного символа. Копирование части строки производится функцией Copy. Вот как:

procedure TForm1.ListBox1Click(Sender: TObject);
var N1, N2, N3: Integer;
S: String;
begin
S:=ListBox1.Items[ListBox1.ItemIndex];
N1:=Pos('(', S); //Позиция символа (
N2:=Pos(')', S); //Позиция символа )
N3:=N2-N1; //Количество копируемых символов
Edit1.Text:=Copy(S, N1, N3);
end;

Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');

Не вышло? Ринат, добавлено 26.07.11, 14:18:08
Все получилось.
спасибо а как сделать чтоб сразу появлялась? без нажатия кнопки? Автор, добавлено 26.07.11, 14:26:54
Я так понимаю, что Delphi вы впервые видите. Так вот, в Delphi ничего само по себе не появляется. Всё происходит при выполнении какого-либо события. Нажатие кнопки Button, или кнопки на клавиатуре, или кнопки мышки, момента появления Формы на экране, изменения текста в компоненте и т.д.

Так что вы имеете в виду под словом "сразу"? В самом начале, при появлении программы? Ринат, добавлено 26.07.11, 21:04:38
Да, вы правы, с программированием я столкнулся впервые.
Я имел ввиду при появление формы на экране. Автор, добавлено 26.07.11, 21:16:14
Появление Формы на экране - это события такого объекта, ну или компонента, как Форма. Посмотрите, щёлкнув по пустому месту на Форме, слева Инспектор Объектов, в него загружены свойства Формы. В Инспекторе Объектов две вкладки - Properties (свойства) и Properties (события). Так вот, те события, на которые может реагировать Форма, находятся на вкладке Properties. За появление Формы на экране отвечает событие OnActivate, хотя лучше всё же воспользоваться OnCreate - событием создания Формы. Поместите в обработчик этого события вышеуказанные операторы.

procedure TForm1.Button1Click(Sender: TObject);
begin
MP1.DeviceType:=dtAutoSelect;
MP1.FileName:='имя_файла';
if not MP1.AutoOpen then MP1.Open;
MP1.Play;
end;

AVI сейчас допишу. Саша, добавлено 10.11.11, 18:19:55
А для этого не надо добавлять какие-то компоненты наподобие таймера или ещё чего-то? Автор, добавлено 10.11.11, 18:41:07
Чтобы просто был звук - больше ничего не надо. Но если вы хотите создать полноценный плейер, то конечно придётся что-то придумывать.

procedure TForm1.Button2Click(Sender: TObject);
begin
MP1.Display:=Panel1;
with OpenDialog1 do
if Execute then
begin
MP1.FileName:=FileName;
MP1.Open;
MP1.Play;
end;
end;

Тут нужно добавить OpenDialog, можно и в предыдущий пример его вставить. И ещё. Размер области воспроизведения, то бишь панели, нужно посмотреть заранее в свойствах файла, на вкладке "Сведения". Но лучше сделать панель побольше, и установить её свойство BevelInner и BevelOuter в bvNone, чтобы её было не видно. А то размеры у файлов разные.

Что касается формата *.3ds, то я не умею работать с 3d видео. Цельная книжка есть про это. Но, блин, изучению надо жизнь посвятить. Но если с вас требуют лабораторку, то наверное преподавали.
Вот, нашёл что нужно иметь модуль GLFile3DS. Он необходим для работы с форматом 3DS. Саша, добавлено 10.11.11, 19:17:47
Спасибо огромное! А что касается *.3ds то как я разговаривал с преподом, то он сказал что надо только показать грудо говоря jpg (или какую-то ещё) проэкцию этого файла но не редактировать его. может тут не надо того модуля? Автор, добавлено 10.11.11, 19:19:09
Не смогу по 3ds подсказать ничего. Звиняйте.

А про avi ещё. Чтобы масштабировать изображение, нужно воспользоваться свойством медиаплейера DispleyRect. Оно доступно только программно. Саша, добавлено 15.11.11, 04:10:29
Я случайно заметил одну особенность: если не создавать панель (Panel1) и не присваивать панели ничего дисплею, то видео выводится в отдельном окне со своим родным расширением.

Но без вопроса не обойдётся =) : как настроить полосу прокрутки для видео или же хотя бы для аудио? Понятно что нужен таймер и и ProgresBar, но как связать это всё во едино? Автор, добавлено 15.11.11, 09:00:43
Когда файл открыт, то свойство Mediaplayer.Length возвращает продолжительность трека в специфическом формате. Лучше всего предварительно задать отображение этой величины в миллисекундах:

Ну далее переводим в часы, минуты и секунды с помощью функции

function taim(Length: Integer): String;
var chas, min, sec: Integer;
function mode(Length: Integer): String;
begin
Result:=IntToStr(Length);
if Length
Это что касается длины. А текущую позицию возвращает свойство. - правильно, Position! Измеряем по срабатыванию таймера и выводим в ProgressBar (лучше возьмите TrackBar). Опять же, свойство TrackBar.Max предварительно установите равным Mediaplayer.Length.

Есть проблемка с прокруткой. Чтобы прокрутить, нужно сначала остановить плеер, и таймер. А затем запустить с другим значением:

Я был удивлён, но TrackBar не имееет событий мыши. А то можно было бы останавливать по событию OnMouseDown. А впрочем, можно пользоваться событием OnEnter! Но запускать всё равно потом приходится.

А чтобы менять кадры при перемотке мышкой, придётся ввести второй таймер, чтобы работал когда воспроизведение останавливается, и задавал

MediaPlayer.Position:=TrackBar.Position;

Время срабатывания естественно сделать поменьше, а то будет тормозить.
Саша, добавлено 16.11.11, 18:59:41
Спасибо! =) Саша, добавлено 17.11.11, 01:24:40
Здравствуйте в очередной раз) Вот какая у меня проблема, когда открываю видео с помощью MedaiPlayer1, то функция Mediaplayer1.Length возвращяет уауое-то кривое значение (например продолжительность видео 40 мин. а возвращает значение примерно 1,17 мин.), но в случае с аудио файлами всё происходит нормально (то есть значение правильное). Но что самое интересное - видео проигрывается свыше возвращенного значения. В чём может быть дело? Автор, добавлено 17.11.11, 02:03:44
Странно. У меня фильм в программе определяется как 1 час 26 минут 55 секунд, с такой программой как Media Player Classic разница несущественная. Вот полный текст программы:

function taim(Length: Integer): String;
var chas, min, sec: Integer;
function mode(Length: Integer): String;
begin
Result:=IntToStr(Length);
if Length
Может вы забыли формат длительности задать? Я закомментировал этот оператор, и продолжительность вместо полутора часов стала две минуты. Саша, добавлено 17.11.11, 03:32:39
Нет, он описан в процедуре TForm1.FormCreate. Но после того, как я удалил его от туда и прописал отдельно для каждой кнопки вызова медиа плеера - всё встало на свои места) Так-что спасибо) Саша, добавлено 20.11.11, 21:56:43
Автор, большое Вам спасибо за этот прекрасный сайт а особенно за ваши ответы на задаваемые вопросы! Я закончил то задание с *.3ds форматом, но дело сдвинулось с мёртвой точки только после того, как Вы написали что нуден модуль GLFile3DS. Как оказалось - это не совсем "сам по себе" модуль) Это часть проекта GLScene. Советую Вам хотя бы не много им поинтересоваться. Полезная вещь. Ещё раз огромное Вам спасибо за помощь и поддержку в трудной ситуации!

ПС
Если надумаете всё таки заняться этим GLScene-ом - то хорошо ищите как правильно его устанавливать. Даже на оф. сайте инструкция не совсем точная. Андрей, добавлено 18.12.11, 02:33:53
помогите, не получается сохранить файл.
пишу такод код, файла нет, ошибок тоже нет:
procedure TForm1.N3Click(Sender: TObject);
begin
with SaveDialog1, Memo1 do
if Execute then
Lines.SaveToFile('ф.txt');
CloseFile(SaveF);
end; Автор, добавлено 18.12.11, 06:59:18
Зачем вам диалог, если вы сохраняете в файл 'ф.txt' - его и ищите. Андрей, добавлено 18.12.11, 11:17:05
если писать вместо ф.txt, FilEname, как в вашем уроке, то файл не сохраняется. Помогите, что я не так делаю. Автор, добавлено 18.12.11, 15:44:10
Вот написали бы именно как делаете, я бы посмотрел. А так приходится гадать. Может, вы Filename в кавычках пишете. Тогда файл будет называться не как в диалоге вы задали, а именно Filename.txt Владимир, добавлено 11.01.12, 23:19:26
Спасибо за уроки начал недавно но кое что уже получается. Изучение затеял с целью
написания электронных тестов для учеников по химии. Однако столкнулся с такой проблемой как на форме разместить например H2O но чтобы 2 была маленькой. Понимаю что вопрос не в тему и может быть не простой но интересует общее направление поиска, больше не кого спросить. Заранее спасибо. Автор, добавлено 12.01.12, 08:30:21
Владимир, вариантов масса. В зависимости от того, как конструктивно построен тест, на каких компонентах. Ведь можно три метки Label рядом стоящие, размер - любой. Или можно картинку нарисовать и поместить в нужное место - компонент Image, или даже просто по Форме написать, на её канве. Владимир, добавлено 12.01.12, 21:23:09
Спасибо буду пробовать. Александр, добавлено 1.05.12, 14:03:59
создал на форме все как положенно, с такимеже названиями.
в код после implementation вставил
begin
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
end ;

но почему-то не работает, при запуске выдает ошибку Александр, добавлено 1.05.12, 15:31:21
аааааааа, надо по форме два раза щелкнуть и писать, понял!! Александр, добавлено 1.05.12, 17:11:13
выручайте.

написал через add все отлично, затем использовал команду Insert.

вылетает ошибка "Debugger exception notification Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0056D0FD in modul 'Project1.exe'.Read of address 0000030C.Process stopped. Use Step or Run to continue."

Аноним, добавлено 1.05.12, 17:36:26
В ошибках разбираться недосуг. Вот как надо:

Memo1.Lines.Insert(0, 'Первая строка');
Александр, добавлено 1.05.12, 17:44:33
вы же в самом начале урока говорите что вот так:

ComboBox1.Items[0] := 'Первая строка изменилась' ;
ListBox1.Items[1] := 'Вторая строка изменилась' ;

я это копирю вставляю в программу и вылазит ошибка Александр, добавлено 1.05.12, 17:54:49
и не понятно почему

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

Как известно, файлы имеют различные форматы и к ним применяются различные программы для обработки. Например, файлы рисунков BMP, текстовые файлы TXT и т.п. Файлы имеют различные имена и определенное расширение, имеющее в среде MS-DOS максимально три символа. Если у файла расширение RAR, то пользователь и операционная система знает, что это архиватор, причем windosw для обработки этого файла применяет средства, указанные в специальном разделе реестра.

Копирование файлов

Для копирования файлов применяется функция CopyFile. Формат ее такой:

CopyFile является функцией, которая возвращает флаг успешной или нет операции копирования.

Например, следующая строка:

Перемещение файлов

Для перемещения файлов применяется функция MoveFile. Она имеет следующий формат:

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

Переименование файлов

У всех вышесказанных командах параметры исходного и конечного файла имеет тип PChar. Это строковый тип с завершающимся нулем. Возможно, вы раньше слышали о таком формате строковых данных. В такую переменную можно занести строку очень большой длины. Ее размер ограничивается наличием нулевого байта в конце. Теоретически такая переменная может иметь бесконечный размер. На практике она ограничивается размерами выделяемой памяти для программы (2Гб).

Преобразование обычной строковой переменной, типа String в PChar производится функцией:

При этом, для команд файловых операций возможны объединение строк. Например:

procedure TForm1.Button1Click(Sender: TObject);

Var InDir,OutDir:String; // объявление строковых переменных

InDir:='c:\1\'; // каталог исходных файлов

OutDir:='c:\2\'; // каталог записуемых файлов

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

В итоге этой процедуры будет копирование файлов c:\1\1.txt и c:\1\2.txt в каталог c:\2. Файлы копируются под теми же именами.

Удаление файлов

Работа с текстовыми файлами. Чтение из текстового файла

На прошлых уроках мы как, в компоненте Memo процесс загрузки и записи текстового файла делался следующим образом:

Все это благодаря свойству Lines, в котором хранятся строки.

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

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

Varf:TextFile; // объявление файловой переменной

st:String; // строковая переменная

AssignFile(f,'c:\1.txt'); // привязка названия файла к файловой переменной

// отключение контроля ошибок ввода-вывода

Reset(f); // открытие файла для чтения

// включение контроля ошибок ввода-вывода

ifIOResult<>0 then // если есть ошибка открытия, то

ShowMessage('Ошибка открытия файла C:\1.TXT');

Exit; // выход из процедуры при ошибке открытия файла

While not EOF(f) do // пока не конец файла делать цикл:

ReadLn(f,st); // читать из файла строку

ShowMessage(st); // выводить строку пользователю

CloseFile(f); // закрыть файл

Прокомментирую некоторые строки этого примера.

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

и являются директивами компилятору, что в этом месту соответственно следует отключить и включить контроль ошибок ввода-вывода. В данном случае при неудачной попытке открытия файла c:\1.txt (файл отсутствует или открыт для записи другой программой) наша программа не выдаст аварийной ошибки и продолжит выполнение данной процедуры. Это свойство полезно для обработки всех возможных случаев в работе программы.

Работа с текстовыми файлами. Запись в текстовый файл

procedure TForm1.Button1Click(Sender: TObject);

Var f:TextFile; // указатель на текстовый файл

AssignFile(f,'c:\1.txt'); // привязка названия к переменной

Append(f); // открыть файл для добавления

if IOResult<>0 then // если ошибка открытия (напр. файла нет)

Rewrite(f); // создать новый файл

if IOResult<>0 then // ошибка создания файла

ShowMessage('Ошибка создания файла C:\1.TXT');

WriteLn(f,'Привет'); // запись в файл строки с символами перевода строки

CloseFile(f); // закрыть файл

Процедура Append(Файл) открывает файл для записи и устанавливает указатель записи в конец файла, т.е. все добавляемые к файлу строки будут записаны в конец файла.

В нашем случае в самом начале файла 1.txt может не оказаться на диске, поэтому команда открытия файла для добавления вызовет ошибку. В этом случае срабатывает наш собственный контроль ошибок и выполняется команда создания файла.

Запись и чтение из файла не текстовых данных

Рассмотрим пример, в котором программа при выходе сохраняет свои размеры и положение окна на экране в файл и при последующем запуске восстанавливает состояние, которое было при выходе. Программа состоит из двух процедур OnShow и OnClose для окна Form1 программы.

procedure TForm1.FormShow(Sender: TObject);

Var f:file of Integer; // файловая переменная, тип integer

i:Integer; // целочистенная переменная

begin

if IOResult<>0 then Exit;

Read(f,i); //считать из файла значение

Form1.Top:=i; // верхнее положение окна

Form1.Left:=i; // левое положение окна

Form1.Width:=i; // ширина окна

Form1.Height:=i; // высота окна

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

Var f:file of Integer;

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

Только не смейтесь! У меня очередной приступ тупости. ))

Вот таким несложным способом мне надо записать несколько строк в файл, но не Writeln,а Write!

записываю в файл.
В Windows Commander нажимаю F3 все красиво, переход на новую строку выполнен, но открываю через F4 (у меня там обычный виндовс блокнот) вижу вместо перехода на новую строку символ в виде квадратика (см. скрин).

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

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

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

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

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

user posted image

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

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

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

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

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

А зачем она нужна?
Она однобайтная, да к тому же и редко когда нужная. На клавиатуре печатной машинки клавиша табуляции, действительно достаточно часто была полезна. На клавиатуре PC? Вот скажите мне. Кто либо из здесь присутствующих когда-либо использовал опцию IDE TurboPascal а затем и Дельфи "Optimal Fill"?

Добавлено через 3 минуты и 48 секунд

Не дай вам бог так же поступать с исходниками ваших программ!

Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!

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


Если я не путаю, то в таком случае криво будет Блокнотом открываться.

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

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

Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!

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

DateSeparator, PathSeparator и др. тоже однобайтовые.

Добавлено через 3 минуты и 23 секунды

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

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

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

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

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

Читайте также: