7
Использование встроенных команд
Языки программирования ничто без встроенной библиотеки полезных команд. Так и PureBasic располагает более 800 встроенных команд для использования в рамках своих программ. Они используются для манипуляций со строками, математическими вычислениями, для обработки файлов и даже графического интерфейса. Они охватывают практически любые мыслимые задачи программирования и если чего то нет, отвечающего вашим потребностям, вы можете создать собственные процедуры. В этой главе я расскажу и объясню наиболее часто используемые встроенные команды PureBasic. Хотя это далеко не полный список, все же это введение должно послужить вам верой и правдой. Эта глава начинается с описания синтаксиса команд из файла справки PureBasic, а затем переходит к фактическому описанию команд и пояснению их. Закончу же эту главу разделом о том, как работать с файлами, например: загрузка, запись или чтение, все с использованием встроенных команд PureBasic.
Использование файла справки PureBasic
Здесь мы постараемся понять как организованы записи на страницах файла справки, как их читать и что более важно, как использовать встроенные команды, которые описаны там. При просмотре страниц в справке вы столкнетесь с такой формой записи:
Синтаксис - Описание - Пример - Поддерживаемые операционные системы.
Все разделы по сути сами объясняют себя, но давайте сконцентрируемся на синтаксисе. В верхней части идет название команды, например: SaveImage(). Давайте найдем ее в файле справке: (Helpfile:Reference Manual->General Libraries->Image->SaveImage). Далее идет раздел синтаксис, примерно так:
SaveImage(#Image, FileName$ [, ImagePlugin [, Flags]])
Первым идет фактическое имя команды, в нашем случае SaveImage после чего идут пара скобок, в которых следуют параметры. В синтаксическом примере показано, что эта команда может принимать четыре параметра. Вы также заметили, что последние два параметра показаны в квадратных скобках. Это означает, что эти последние два параметра являются необязательными, и могут не использоваться для вызова SaveImage(). Давайте посмотрим на примеры с использованием необязательных параметров и без них:
SaveImage(1, "Image.bmp")
SaveImage(1, "Image.jpg", #PB_ImagePlugin_JPEG)
SaveImage(1, "Image.jpg", #PB_ImagePlugin_JPEG, 10)
Первый пример будет сохранить изображение с именем image.bmp по умолчанию в 24 битовый растровый формат. Второй пример будет сохранить изображение в формате JPEG и использовать стандартную степень сжатия. Третий пример будет сохранить изображение в формат JPEG и использовать максимальное значения сжатия 10!
Квадратные скобки в рамках примеров
Квадратные скобки, показанные в синтаксических примерах никогда не используются при использовании этих команд. Они только отделяют в примерах необязательные параметры для лучшего понимания, но в реальном коде их быть не должно. Квадратные скобки в реальном коде используются только для статических массивов см. главу 5.
Вызов встроенных команд чем похож на вызов процедур. Каждая из встроенных команд должна вызываться с правильным синтаксисом передачи параметров, иначе компилятор оповестит вас об ошибках в коде. Структура приведенного выше примера синтаксиса доминирует по всему файлу справки, поэтому если вы поняли синтаксис этот примера, вам не составит труда понять и другие.
PB Числа и OS идентификаторы
При использовании встроенных команд, важно понимать роль нумерации объектов PureBasic а так же идентификаторов операционной системы , так как они непосредственно используются при управлении программой. Оба являются не более чем цифры, и оба используются для идентификации объектов в программах. Например, чтобы определить части графического интерфейса пользователя или различные изображения. Знание как и когда использовать их, имеет важное значение не только для PureBasic но в программировании в целом. Справка PureBasic имеет большое кол-во информации, но она может быть немного непонятной при использовании нумерации объектов PureBasic и идентификаторами операционной системы . Попробуем разобраться получше:
PB числа
PureBasic работает на нескольких системах и использует свою нумерацию для идентификации каждого объекта в вашей программе. Этим объектом может быть окно, гаджет или файл изображения. PB числа используются в программе для того, чтобы ссылаться на эти объекты позже, при выполнении определенных действий, связанных с ними. Многим командам необходимо один или два PB числа в качестве параметров. Они приводятся в справке PureBasic в синтаксическом примере любой команды. Числа PB обычно показаны как константы. Начинаются с решетки (#) и заканчиваются названием библиотеки, которая находится в команде. Вот пример (Helpfile:Reference Manual->General Libraries->Image->CreateImage):
CreateImage(#Image, Width, Height)
Как вы можете видеть, первым параметром, показана константа #Image. Но это не означает, что использование константы является обязательным. Можно использовать любое целое число для объекта, лишь бы оно было уникальным среди других объектов такого типа. Это число для созданного объекта будет закреплено за ним на протяжении всей программы.
Одинакового типа объекты могут конфликтовать с одинаковыми PB числами
PureBasic числа обеспечивают отличный способ для обозначения всего, что создает PureBasic на индивидуальной основе. Из-за этого вы не можете иметь два одинаковых объекта с одним номером. Если вы создадите изображение с номером 1, а затем вы создадите еще одно изображение с номером 1, PureBasic автоматически уничтожает первое и освободит память для создания второго.Эта функция очень удобна, для замены объектов в любое время. Одинаковые числа можно использовать для объектов из разных библиотек. Они не будут конфликтовать. Но в коде это может вызвать путаницу для вас самих. Поэтому многие программисты, при использовании разных команд для создания объектов, используют константы вместо чисел. Эти константы обычно определяются в блоке перечисления. Вот пример:
Enumeration
#IMAGE_DOG
#IMAGE_CAT
#IMAGE_BIRD
EndEnumeration
CreateImage(#IMAGE_DOG, 100, 100)
CreateImage(#IMAGE_CAT, 250, 300)
CreateImage(#IMAGE_BIRD, 450, 115)
После того как константы были определены, я могу использовать их для создания изображений и не беспокоиться о конфликтах с индефикацией. В течение программы я могу использовать эти константы для обозначения изображения прямо по имени. Например, теперь я могу сослаться на первое изображение с помощью константы #IMAGE_DOG . Этот метод использования констант для чисел PureBasic гарантирует четко организованный и читаемый код.
Динамические PB числа
В качестве альтернативы использованию блоков перечисления для обработки вновь созданных объектов, вы можете использовать специальную константу. Эта константа:
#PB_Any
Эта константа может использоваться везде, где PB число ожидается в команде создания объекта. Это бывает нужно для построения динамических программ, где вы не можете знать, сколько объектов будет создаваться. Каждой в конце концов будет присвоен свой иденфикатор Вот пример:
ImageDog.l = CreateImage(#PB_Any, 100, 100)
Иденфикаторы операционной системы
Некоторым объектам, создаваемым с помощью встроенных команд PureBasic, присваиваются номера операционной системы. За этими значениями следит операционная система. Это например окна, шрифты и изображения, и т.д. В справке PureBasic они указываются как ID. При программировании в PureBasic вы заметите, что некоторые команды потребуют в качестве параметров идентификаторы ОС. Вот несколько команд, которые возвращают идентификатор ОС:
WindowOSId.l = WindowID(#Window)
GadgetOSId.l = GadgetID(#Gadget)
ImageOSId.l = ImageID(#Image)
Я перечислил здесь три , но есть еще несколько. Названия команд, которые заканчиваются обычно ID() возвращают ОС идентификаторы. Вот пример команды, которая использует ОС идентификатор в качестве параметра:
CreateGadgetList(WindowOSId)
Эта команда используется для создания списка гаджетов в окне и использует операционную систему для определения идентификаторов, в которой создается список. Идентификатор ОС используется с этой командой вместо PB числа для максимальной совместимости, только в случае, если окно было создано с помощью API операционной системы. Если вы хотите использовать эту команду, чтобы создать список гаджетов окна, созданного с помощью системы счисления PureBasic, то можно так:
CreateGadgetList(WindowID(#Window))
Мы используем команду WindowID() в качестве параметра, который возвращает идентификатор окна ОС с помощью РВ числа . Каждая операционная система имеет собственный интерфейс прикладного программирования или API для краткости. Это встроенная команда используется для всех языков программирования и служит для создания интерфейса. Идентификаторы используются для отслеживания и доступа ко всем объектам, которые содержит операционная система . Все ОС идентификаторы являются уникальными для каждой программы, даже не написанной в PureBasic. Операционная система для отслеживания тысяч наименований, использует длинные номера из 8 цифр, так что не удивляйтесь. ОС идентификаторы могут быть не использованы для создания программ PureBasic, но начинающие должны знать, что когда нибудь настанет время для использования их. ОС идентификаторы играть важную роль при использовании API любой операционной системы, в особенности Windows API, об этом чуть больше в главе 13.
Примеры общих команд
В этом разделе я собираюсь продемонстрировать некоторые из наиболее часто используемых команд в PureBasic. Обычно эти команды используются в большинстве программ PureBasic, поэтому обучение их синтаксиса будет только полезным. Все эти команды существуют в различных библиотеках. Здесь они представлены ниже в алфавитном порядке.
Asc()
(Helpfile:Reference Manual->General Libraries->String->Asc)
Синтаксис: ASCIIValue.l = Asc(Character.s)
Эта команда возвращает ASCII значения строки. В стандартный наборе символов ASCII цифры от 0 до 255 используются для представления символов и кодов управления компьютером. Передаваемым параметром этой команды является строка, и команда Asc возращает ASCII код одного символа этой строки, в данном случае первого. На следующем примере возвращаются все символы строки:
Text.s = "This is a test"
For x.l = 1 To Len(Text)
Debug Mid(Text, x, 1) + " : " + Str(Asc(Mid(Text, x, 1)))
Next x
С помощью цикла FOR-NEXT и команды Mid, передаются по очереди все символы в качестве параметров команде ASC. Она выдает ASCII коды для них и конечно все они выводятся в окно отладки.
Chr()
(Helpfile:Reference Manual->General Libraries->String->Chr)
Синтаксис: Character.s = Chr(ASCIIValue.l)
Эта команда возвращает один символ из полученного кода ASCII. Эта команда прямая противоположность ASC. Параметром служит число от 0 до 255.
Text.s = Chr(84) + Chr(104) + Chr(105) +
Chr(115) + Chr(32)
Text.s + Chr(105) + Chr(115) + Chr(32)
Text.s + Chr(97) + Chr(32)
Text.s + Chr(116) + Chr(101) + Chr(115) + Chr(116)
Debug Text
Приведенный выше пример строит строку This is a test за счет
сложения нескольких Chr() команд. Например, первая команда Chr(84)
возвращает символ T. См. приложение файла справки полного
списка ASCII таблицы, показывающей все символы и связанных с этими
символами числа от 0 до 255.
Delay()
(Helpfile:Reference Manual->General Libraries->Misc->Delay)
Синтаксис: Delay(Milliseconds)
Эта команда паузы для деятельности всей программы на срок, указанный в параметре в миллисекундах. (Миллисекунда является одной тысячной секунды).
Debug "Start..."
Delay(5000)
Debug "This is executed 5 seconds later"
После запуска программы высветится в окне отладки Start.. Затем ожидание 5 секунд. Далее высветится This is executed 5 seconds later. И программа завершится.
ElapsedMilliseconds()
(Helpfile:Reference Manual->General Libraries->Misc->ElapsedMilliseconds)
Синтаксис: Result.l = ElapsedMilliseconds()
Эта команда возвращает количество миллисекунд, прошедших с определенного ранее времени.
Debug "Start..."
StartTime.l = ElapsedMilliseconds()
Delay(5000)
Debug "Delayed for "+Str(ElapsedMilliseconds() - StartTime)+"
milliseconds."
Эта команда может понадобиться, чтобы выполнить любой вид синхронизации в вашей программе. Например, если нужно измерить какой то промежуток времени, вы первоначально задаете команду ElapsedMilliseconds(), далее запускаете таймер, и снова с помощью команды ElapsedMilliseconds() делаете вычисление промежутка времени. Чтобы получить результат, вычтите из времени окончания начальное время. Все продемонстрировано в вышеупомянутом примере. Когда вы используете эту команду впервые, вы можете быть потрясены возращенным большим числом. Вы должны помнить, что запись делается миллисекундах.
FindString()
(Helpfile:Reference Manual->General Libraries->String->FindString)
Синтаксис: Position.l = FindString(String.s, StringToFind.s, StartPosition.l)
Эта команда ищет параметр StringToFind в рамках параметра String, начиная с позиции, указанной параметром StartPosition. Если с параметром 1, он находит эту строку сразу возвращает позицию 1.
String.s = "I like to go fishing and catch
lots of fish"
StringToFind.s = "fish"
FirstOccurrence.l = FindString(String, StringToFind, 1)
SecondOccurrence.l = FindString(String, StringToFind, FirstOccurrence +
1)
Debug "Index of the first occurrence: " + Str(FirstOccurrence)
Debug "Index of the second occurrence: " + Str(SecondOccurrence)
Этот пример показывает, как найти строку в другой строке. Первым делом команда FindString() пытается найти строку FISH начиная с позиции 1. Поиск успешен и в переменную FirstOccurrence заносится значение 14. Это как раз место в строке I like to go fishing and catch lots of fish , по которому стоит искомая FISH. Следующий поиск ведется с 15 места. Поскольку FirstOccurrence+1=15. Поиск опять оказался успешным, и на этот раз строка FISH найдена на позиции 40. Это число заносится в переменную SecondOccurrence И под конец оба результата выведены в окно отладки.
Len()
(Helpfile:Reference Manual->General Libraries->String->Len)
Синтаксис: Length.l = Len(String.s)
Эта команда возвращает длину строки, то есть кол-во символов в строке, которая идет в качестве параметра для команды.
Alphabet.s = "abcdefghijklmnopqrstuvwxyz"
LengthOfString.l = Len(Alphabet)
Debug LengthOfString
Этот очень простой пример команды Len(). Переменной Alphabet присваивается строка с символами. Далее переменной LenghtOfString присваивается значение, которое будет обработано командой Len() с параметром Alphabet . И значение переменной LengthOfString выводится в окне вывода отладки.
MessageRequester()
(Helpfile:Reference Manual->General Libraries->Requester->MessageRequester)
Синтаксис: Result.l = MessageRequester(Title.s, Text.s [, Flags])
Возможные Flags:
#PB_MessageRequester_Ok
#PB_MessageRequester_YesNo
#PB_MessageRequester_YesNoCancel
Возможные возращаемые значения:
#PB_MessageRequester_Yes
#PB_MessageRequester_No
#PB_MessageRequester_Cancel
Эта команда используется для создания небольшого окна, которое может показывать любую информацию в вашей программе. Она может быть использована в любом месте программы. Первый параметр в этой команде, это строка, отображаемая в строке заголовка окна. Вторым параметром является фактическая строка сообщения, отображаемая в самом окне. Третий и последний параметр для необязательных флагов. С помощью разных флагов в последнем параметре, вы можете изменить стиль окна запроса, включением различных кнопок. Ваша программа будет остановлена, пока одна из этих кнопок не будет нажата. Чтобы понять лучше назначение каждой из них пример:
Title.s = "Information"
Message.s = "This is the default style message requester"
MessageRequester(Title, Message, #PB_MessageRequester_Ok)
Message.s = "In this style you can choose 'Yes' or 'No'."
Result.l = MessageRequester(Title, Message, #PB_MessageRequester_YesNo)
If Result = #PB_MessageRequester_Yes
Debug "You pressed 'Yes'"
Else
Debug "You pressed 'No'"
EndIf
Message.s = "In this style you can choose 'Yes' or 'No' or 'Cancel'."
Result.l = MessageRequester(Title, Message,
#PB_MessageRequester_YesNoCancel)
Select Result
Case #PB_MessageRequester_Yes
Debug "You pressed 'Yes'"
Case #PB_MessageRequester_No
Debug "You pressed 'No'"
Case #PB_MessageRequester_Cancel
Debug "You pressed 'Cancel'"
EndSelect
Этот пример показывает различные способы использования команды MessageRequester. Он также показывает вам понять, как использовать константы возвращаемого значения для определения того, какая была нажата кнопка. Использование констант, помогает не беспокоиться по поводу запоминания числовых значений. Вам не нужно знать, какие значения присваиваются этим константам, важно знать равны они или нет возвращаемому значению.
Mid()
(Helpfile:Reference Manual->General Libraries->String->Mid)
Синтаксис: Result.s = Mid(String.s, StartPosition.l, Length.l)
Эта команда возвращает строку, которая вырезана из другой строки. Первым параметром является строка из которой нужно вырезать нужный отрывок. Вторым параметром является стартовая позиция для будущей вырезанной строки. Третий параметр это длина будущей строки. Вот пример:
StartingString.s = "Hickory Dickory Dock"
ExtractedString.s = Mid(StartingString, 17, 4)
Debug ExtractedString
Здесь я извлекаю строку Dock, задав начальную позицию 17, с длиной 4 символа. Подобно команде FindString() позиция в исходной строке измеряется в символах.
Random()
(Helpfile:Reference Manual->General Libraries->Misc->Random)
Синтаксис: Result.l = Random(Maximum.l)
Эта команда просто возвращает случайное число между нулем и значением, определенным в параметре включительно.
Debug Random(100)
В приведенном выше примере команда Random() вернет случайное значение в диапазоне от 0 до100 включительно.
Str(), StrF(), StrQ(), StrD()
(Helpfile:Reference Manual->General Libraries->String->Str)
Синтаксис:
Result.s = Str(Value.b)
Result.s = Str(Value.w)
Result.s = Str(Value.l)
Result.s = StrF(Value.f [, DecimalPlaces.l])
Result.s = StrQ(Value.q)
Result.s = StrD(Value.d [, DecimalPlaces.l])
Эти четыре команды по сути одинаковы. Их основное использование: переводить числа в строки. Str() для обработки чисел с типом .b (byte) .w (word) и .l (long). StrF() используется для обработки чисел с типом .f (Float). StrQ() для обработки чисел с типом .q (Quads). StrD() для преобразования чисел с типом .d (Doubles) В случае с StrF() и StrD() вы заметили, что существует также дополнительный параметр называющийся DecimalPlaces. Если используется этот параметр, то он определяет, сколько знаков после запятой преобразовать с округлением, остальные будут отрезаны
Debug "Long converted to a String: " +
Str(2147483647)
Debug "Float converted to a String: " +StrF(12.05643564333454646, 7)
Debug "Quad converted to a String: " +StrQ(9223372036854775807)
Debug "Double converted to a String: " +StrD(12.05643564333454646, 14)
Приведенный пример показывает, как преобразовать четыре различные числовые значения в строки. В каждом случае после преобразования они выводятся в окне вывода отладки. Важно помнить: если вы не используете параметр DecimalPlaces, то в случае с StrF() по умолчанию будут преобразованы только шесть знаков после запятой, а в случае с StrD() десять знаков.
Val(), ValF(), ValQ(), ValD()
(Helpfile:Reference Manual->General Libraries->String->Val)
Синтаксис:
Result.l = Val(String.s)
Result.f = ValF(String.s)
Result.q = ValQ(String.s)
Result.d = ValD(String.s)
Эти четыре команды по сути прямая противоположность команде STR(). То есть эта команда возвращает числовые значения из строк. Вот простой пример:
LongTypeVar.l = Val("2147483647")
FloatTypeVar.f = ValF("12.05643564333454646")
QuadTypeVar.q = ValQ("9223372036854775807")
DoubleTypeVar.d = ValD("12.05643564333454646")
Debug LongTypeVar
Debug FloatTypeVar
Debug QuadTypeVar
Debug DoubleTypeVar
В этом примере я использовал все четыре различных типа данных с командой Val() для преобразования четырех строк в их числовые типы. Вы должны помнить, что если в заложенных типах используются значения большие чем должны быть, то конечный результат сбивается, то есть становится не корректным.
Работа с файлами
Использование файлов является естественным для любой программы, как для хранения так и для извлечения данных. PureBasic обеспечивает полную поддержку для чтения и записи файлов, и может читать и записывать любое количество файлов практически одновременно. Описание всех команд обработки файлов вы можете найти в файле справки:
(Helpfile:Reference Manual->General Libraries->File)
Я не буду объяснять все команды описанные в вышеупомянутом разделе, но объясню команды для чтения и записи файлов. А остальные команды вы легко поймете, при первом же использовании их.
Запись в файл
Давайте начнем с примера о том, как писать некоторые данные в файл, то здесь мы напишем несколько строк в простой текстовый файл.
#FILE_RHYME = 1
Dim Rhyme.s(3)
Rhyme(0) = "Baa baa black sheep, have you any wool?"
Rhyme(1) = "Yes sir, yes sir, three bags full!"
Rhyme(2) = "One for the master, one for the dame,"
Rhyme(3) = "And one for the little boy who lives down the lane."
If CreateFile(#FILE_RHYME, "Baa baa.txt")
For x.l = 0 To 3
WriteStringN(#FILE_RHYME,
Rhyme(x))
Next x
CloseFile(#FILE_RHYME)
EndIf
Для начала я использовал константу #FILE_RHYME для нумерации(идентификации) нашего файла. Далее я определил строковой массив, содержащий четыре ячейки со строками, в которых записан детский стишок. Далее перейдем к записи его в файл. Если бы я хотел записать стишок в существующий файл, тогда я бы использовал команду OpenFile(), но в приведенном выше примере, я хочу записать в новый файл, поэтому я использую команду CreateFile() Эта команда имеет два параметра: первый уникальный идентификатор файла, а второй имя создаваемого файла. После проверки на создания файла и возврата TRUE(истина), программа перейдет к циклу FOR-NEXT. Если не использовать проверку, может случится так, что файл по каким то причинам не создается. Это вызовет ошибки в программе, что чревато вылетом или зависанием программы.
Для записи строк в файл, я использовал команду WriteStringN(). Она имеет два параметра. Первый: идентификатор файла, в который будет осуществлена запись. А второй собственно сама строка, которую надо записать. Я использовал цикл для считывания из массива, и записи считанных строк в файл. Команда WriteStringN() используемая в этом примере представляет собой расширенную команду WriteString(). На самом деле единственное различие заключается в букве N перед скобками. Этот символ в команде означает, что при следующем вызове команды (WriteString() илиWriteStringN()) запись будет с новой строки. Когда запись в файл закончена, я закрываю файл, используя команду CloseFile()У нее есть всего один параметр - это идентификатор файла , который надо закрыть.
Различные способы создания или открытия файлов
При использовании команд для работы с файлами (чтения или записи) нужно выбрать правильную команду в зависимости от того, как вы хотите использовать этот файл. В приводимом ниже списке описываются команды для записи и чтения:
ReadFile() Открывает файл только для чтения
OpenFile() Открывает файл для чтения или записи. Так же создает его, если он не существует.
CreateFile() Создает пустой файл для записи. Если файл уже существует, он заменяет его пустым.
Все команды имеют по два параметра. Первым параметром является идентификатор файла, с которым будет работать программа, вторым параметром является фактическое имя файла на диске.
Этот файл, содержащий детский стишок, должен сейчас быть где-то на вашем жестком диске. Если вы создаете файл, используя относительное имя файла, такое как Baa baa.txt , то созданный файл будет находиться в том же каталоге, что и файл исходного кода. Если же вам нужен файл, который будет создан в каком-то конкретном месте, вы должны указать полный путь, который должен включать имя диска, директорий и имя файла. Пример:
...
If CreateFile(#FILE_RHYME, "C:\My Directory\Baa baa.txt")
...
При использовании этого метода, всегда нужно убедиться, что все каталоги, указанные в пути существуют, прежде чем записать файл, в противном случае создание файла не удастся.
Важность команды CloseFile()
Когда вы закончили чтение, и особенно запись файлов, вы должны закрыть файл командой CloseFile(). Эта команда не только закрывает выбранный файл, но освобождает его для других программ. Еще одна важная роль команды CloseFile() в том, что она полностью записывает в файл любые данные, которые были оставлены в буфера файла . PureBasic использует системный буфер для увеличения производительности доступа к файлу, так что если вы открываете файл в другом редакторе, а некоторых данных будет там не хватать, вы должны проверить, что вы закрыли файл правильно используя CloseFile(). Для новичков в программировании, я думаю не стоит забивать голову знаниями о буфере файла, нужно просто закрывать файлы каждый раз, когда вы закончите с ним работу, во избежание любых ошибок.
Запись других встроенных типов данных
Запись других типов данных происходит точно так же как и запись строк. Теперь, когда вы понимаете, как работает WriteString(), по аналогии не трудно понять и другие команды для записи данных. Вот пример синтаксиса для написания других встроенных типов данных:
WriteByte(#File, Value.b)
WriteChar(#File, Value.c)
WriteWord(#File, Value.w)
WriteLong(#File, Value.l)
WriteQuad(#File, Value.q)
WriteFloat(#File, Value.f)
WriteDouble(#File, Value.d)
Эти команды могут быть использованы для записи любого встроенного типа значений в файл, а все команды можно использовать столько раз, сколько захотите. Параметров как и у WriteString() два. аналогично первым идет идентификатор файла, вторым данные, которые надо записать.
Чтение из файлов
Чтение из файлов так же просто, как и запись в них. Посмотрите на следующий пример: в нем читаются строки из файла с именем Report.txt, и помещаются в связный список с именем FileContents. Содержание этого связанного списка затем выводится в окне вывода отладки просто для наглядности.
#FILE_REPORT = 1
NewList FileContents.s()
If ReadFile(#FILE_REPORT, "Report.txt")
While Eof(#FILE_REPORT) = #False
AddElement(FileContents())
FileContents() = ReadString(#FILE_REPORT)
Wend
CloseFile(#FILE_REPORT)
EndIf
ForEach FileContents()
Debug FileContents()
Next
В начале кода я использовал константу, для идентификации(нумерации) файла. Затем создал связанный список с именем FileContents. Вы можете не использовать связанный список для чтения строк, просто я считаю, что это удобно. Я использовал связанный список здесь, потому что они легок в использовании и может расти вместе с новыми пунктами, в отличие от массивов, размерность которых определена. Открываем файл, используя команду ReadFile(). Как вы помните, это открывает его только для чтения. Разрешения на запись отсутствуют. Как и прежде c CreateFile(), я использовал команду ReadFile() в рамках логического оператора IF-ENDIF. После того как файл открыт, мне нужна информация только для чтения. Я использовал цикл While-Wend для повторных команд чтения строки. Цикл работает пока не будет достигнут конец файла. В этом помогает команда EOF(). Как только эта команда вернет истину(то есть достигнут конец файла), чтение прекратится. Каждый раз при прохождении цикла, читается новая строка и заносится в связанный список. После прекращения работы цикла командой CloseFile() закрывается файл и передается управление другому циклу ForEach-Next, который считывает данные из связанного списка и выводит их в окно отладки.
Чтение других типов данных из файла
Хотя последний пример касается строк, можно также легко прочитать другие типы данных из файла. PureBasic предусматривает конкретные команды для каждого из встроенных типов данных:
ReadByte(#File)
ReadChar(#File)
ReadWord(#File)
ReadLong(#File)
ReadQuad(#File)
ReadFloat(#File)
ReadDouble(#File)
Для простоты, все эти команды схожи с командой ReadString(). Единственное различие между этими командами то, что ReadString() считывает всю строку, а эти команды считывают только одно значение из файла, которое записано в имени команды. То есть команда ReadLong() считает только четыре байта. Далее указатель доступа к файлу перемещается вперед на 4 байта, для чтения других 4 байт.
Указатель доступа к файлам
В рамках каждого открытого файла существует невидимый указатель доступа к файлу. Эта мнимая позиция, откуда вы будете читать или записывать данные в открытом файле. При использовании ReadFile(), OpenFile() или CreateFile() команд, доступ указателя начинается с начала файла, и готов к следующей операции. Как только вы начинаете чтение или запись, указатель доступа к файлу начинает движение. Если идет запись в файл, то доступ указателя будут осуществляться на основе ее, двигаясь на позицию сразу после получения последнего записанного значения, готовый к следующей операции. Если вы читаете из файла, то доступ указателя будет двигаться к концу файла и достигнет его как только команда Eof () = 0(#False)Получение позиции указателя
Во время чтения или записи в файл, вы можете получить расположение указателя доступа к файлам с помощью команды Loc(). Возвращаемое значение измеряется байтами.
(Helpfile:Reference Manual->General Libraries->File->Loc)
Синтаксис: Position.q = Loc(#File)
Эта команда вернет позицию указателя доступа к файлу (в байтах), указанного в параметре #File. Значение позиции возвращается восьмибайтовым числом(Quad) для поддержки больших файлов.
Перемещение указателя в файле
Указатель доступ к файлам может быть перемещен в любое время с помощью команды FileSeek() .
(Helpfile:Reference Manual->General Libraries->File->FileSeek)
Синтаксис: FileSeek(#File, NewPosition.q)
Эта команда имеет два параметра: первый номер(идентификатор)файла, вторым, является новая позиция (в байтах) указателя доступа к файлу. Она позволяет читать с любой позиции, в рамках какой-то файла в любое время. Параметр NewPosition должен быть восьмибайтовым(Quad) числом для поддержки больших файлов.
Выяснение текущего размера файла
Чтобы узнать размер файла, можно использовать команду Lof(), высчитывающую длину файла в байтах.
(Helpfile:Reference Manual->General Libraries->File->Lof)
Синтаксис: Length.q = Lof(#File)
Эта команда вернет размер файла, указанного в параметре #FILE в байтах. Длина возвращается числом с типом Quad для поддержки больших файлов.
Пример для Loc, Lof и FileSeek
В следующем примере я собираюсь продемонстрировать использование Loc(), Lof() и FileSeek(). В приведенном ниже коде я читаю музыкальный файл MP3 и пытаюсь обнаружить, ID3 (V1) тег, встроенный внутри него. Эти теги обычно содержат информацию, такую как имя исполнителя, название песни и жанр, и т.д. После чтения спецификаций в формате MP3 ID3 тэгов в Интернете, я обнаружил, что теговая информация всегда добавляется в конец MP3-файла и этот тег всегда 128 байт. Спецификация упоминает, что первые 3 байта этого тега символы Tag. Вот это и проверяется данным примером:
#FILE_MP3 = 1
MP3File.s = "Test.mp3"
If ReadFile(#FILE_MP3, MP3File)
FileSeek(#FILE_MP3, Lof(#FILE_MP3) - 128)
For x.l =
1 To 3
Text.s + Chr(ReadByte(#FILE_MP3))
Next x
CloseFile(#FILE_MP3)
If Text =
"TAG"
Debug "'" + MP3File + "' has an ID3v1 tag embedded within it."
Else
Debug "'" + MP3File + "' does not have an ID3v1 tag embedded within it."
EndIf
EndIf
После открытия файла с помощью ReadFile() перемещаем указатель в нужное место. Выяснив длину файла отнимаем от нее 128 байт и перемещаем указатель на это значение:
FileSeek(#FILE_MP3, Lof(#FILE_MP3) - 128)
После того как указатель оказался на нужном месте, мы используем цикл для чтения первых трех байт из 128 последних. Эти три байта помещаем в переменную Text. Потом закрываем файл с помощью CloseFile(). И с помощью команд IF-ENDIF в зависимости от условий выводится соответствующее сообщение в окне отладки.
Читайте файл справки
Все больше становится хороших программистов особенно на интернет-форумах. Чтобы по-настоящему понять что то, надо учиться. И чтобы выучиться, надо прочесть немало. В действительности не скрывают того факта, что люди, которые читают больше о предмете, как правило, лучше понимают его. Это особенно подходит для языков программирования. Лучший совет, который я могу дать вам, для обучения PureBasic, это чтение справки к PureBasic. Прочитать все о каждой команде. Это звучит очень скучно, но поверьте это приведет к существенному увеличению вашего понимания о PureBasic и даст вам отличное представление, что просто можно с помощью этого великого языка. Надеемся, эта глава даст вам достаточно понимания, чтобы без проблем читать справку и понять, как использовать большинство встроенных команд.