Документация Engee

Функции ввода/вывода

Функции ввода/вывода (Input/Output) в Julia предоставляют возможность работы с файлами, потоками данных и другими источниками/приемниками данных (подробнее см. здесь). Для файлов, импортированных в файловый браузер, могут применяться функции:

Открытие

open — открытие файла или потока данных.

Details

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

Функция применяет функцию f к результату open(args...; kwargs...) и закрывает дескриптор результирующего файла по завершении.

open(f::Function, args...; kwargs...)

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

write("my_file.txt", "Hello world!"); #создается файл my_file.txt, содержащий текст Hello world!

open(io->read(io, String), "my_file.txt")
"Hello world!" #открывает my_file.txt для чтения и сразу же читает его содержимое в строку

rm("my_file.txt") #удаляет my_file.txt после того, как его содержимое было прочитано и выведено

Функция io->read(io, String), которая принимает объект ввода/вывода (io) и читает его содержимое в строку. После этого содержимое файла "my_file.txt" выводится в качестве результата, и в конечном итоге получается строка "Hello world!".


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

open(filename::AbstractString; lock = true, keywords...) -> IOStream

Ключевое слово

Описание

По умолчанию

read
write
create
truncate
append

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

!write
truncate | append
!read & write | truncate | append
!read & write
false

По умолчанию, если ключевые слова не передаются, файлы будут открыты только для чтения. Возвращается поток для доступа к открытому файлу. Именованный аргумент lock определяет, будут ли операции заблокированы для безопасного многопотокового доступа.

Альтернативный синтаксис открытия, в котором вместо пяти логических аргументов используется описатель режима, основанного на операциях со строками. Значения mode соответствуют значениям из fopen(3) или Perl open и эквивалентны настройке следующих логических групп:

Режим

Описание

Ключевые слова

r
w
r+
w+
a+

чтение
чтение, создание, обрезка
чтение, создание, присоединение
чтение, запись
чтение, запись, создание, обрезка
чтение, запись, создание, присоединение

нет write = true
append = true
read = true, write = true
truncate = true, read = true
append = true, read = tru

Примеры:

io = open("my_file.txt", "w"); #открывает my_file.txt для записи (write)

write(io, "Hello world!"); #записывает строку Hello world! в файл, который был открыт для записи в предыдущей строке

close(io); #закрывает my_file.txt, освобождая ресурсы и завершая операцию записи

io = open("my_file.txt", "r"); #открывает my_file.txt для чтения (read), возвращает объект ввода/вывода (io)

read(io, String) #читает содержимое файла my_file.txt как строку
"Hello world!" #результат операции

write(io, "This file is read only") #поскольку файл был открыт только для чтения (в предыдущей строке), эта операция записи не разрешена и выдаст ошибку ArgumentError
ERROR: ArgumentError: write failed, IOStream is not writeable
[...]

close(io) #закрывает файл my_file.txt после попытки записи, чтобы освободить ресурсы

io = open("myfile.txt", "a"); #открывает my_file.txt для добавления (append), что позволит записывать данные в конец файла без удаления или перезаписи его содержимого

write(io, "This stream is not read only") #записывает строку "This stream is not read only" в конец файла my_file.txt, так как файл был открыт в режиме добавления ("a"). Функция write возвращает количество записанных байтов (28)
28 #результат операции

close(io)#закрывает my_file.txt после выполнения всех операций записи, чтобы освободить ресурсы

rm("my_file.txt") #удаляет файл my_file.txt

Подробнее о всех возможностях функции open читайте здесь.

isopen — определяет закрыт ли уже объект (поток или таймер).

Details

После того как объект будет закрыт, он уже не сможет создавать новые события. Однако учитывая, что закрытый поток по-прежнему может содержать данные для чтения в буфере, следует использовать eof, чтобы проверить возможность чтения данных. Используйте пакет FileWatching для получения уведомлений в случае, если поддерживается запись в поток или чтение из него. Функция выводит true в случае если объект открыт и false если объект закрыт.

io = open("my_file.txt", "w+"); #открывает файл my_file.txt в режиме "w+" (записи и чтения)

isopen(io) #проверяет, открыт ли файл, связанный с объектом ввода/вывода io (my_file.txt)
true #результат операции

close(io) #закрывает файл, связанный с объектом ввода/вывода io, после закрытия файл больше не доступен для записи или чтения

isopen(io) #после того как файл был закрыт (предыдущая операция), команда возвращает false, потому что файл уже не открыт
false #результат операции

Для функции io = open("my_file.txt", "w+"):

  • Если файл не существует, он будет создан.

  • Если файл уже существует, его содержимое будет удалено.

Функция open также возвращает объект ввода/вывода (io), который связан с открытым файлом.

Закрытие

close — закрывает поток ввода/вывода.

Details

Сначала выполняется flush (принудительный сброс ввода/вывода).

close(io)

closeall — закрывает все открытые окна графического интерфейса пользователя.

Details

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

closeall()

closeread — закрывает только поток чтения из файла, связанный с объектом ввода/вывода.

Details

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

closeread(io)

closewrite — прекращает запись половины полнодуплексного потока ввода/вывода.

Details

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

Примеры:

io = Base.BufferStream(); #создается новый буферизованный поток ввода/вывода. В этом случае блокировка никогда не выполняется, поэтому операции чтения и записи доступны для того же задания

write(io, "request"); #строка request записывается в буферизованный поток io

# при вызове здесь `read(io)` применяется постоянная блокировка

closewrite(io); #закрывается поток записи в io и не будут приниматься операции записи, при этом поток чтения остается открытым

read(io, String) #выполняется операция чтения из io

Запись

write — записывает представление канонического двоичного файла значения в заданный поток ввода/вывода или файл.

Details

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

Можно выполнить запись нескольких значений с вызовом одного write, то есть следующие значения являются эквивалентными:

write(io, x, y...)
write(io, x) + write(io, y...)

Примеры:

#Согласованная сериализация

fname = tempname(); # произвольное временное имя файла

open(fname,"w") do f
             # Убедиться в том, что выполняется запись 64-разрядного целочисленного значения в формате прямого порядка следования байтов
             write(f,htol(Int64(42)))
         end
8

julia> open(fname,"r") do f
             # Выполнить обратное преобразование в основной порядок следования байтов и основной целочисленный тип
             Int(ltoh(read(f,Int64)))
         end
42

#Объединение вызовов операций записи:

io = IOBuffer();

write(io, "JuliaLang is a GitHub organization.", " It has many members.")
56

String(take!(io))
"JuliaLang is a GitHub organization. It has many members."

write(io, "Sometimes those members") + write(io, " write documentation.")
44

String(take!(io))
"Sometimes those members write documentation."

#Определяемые пользователем типы основных данных без методов write можно записать, а заметим инапсулировать в Ref

struct MyStruct; x::Float64; end

io = IOBuffer()
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)

write(io, Ref(MyStruct(42.0)))
8

seekstart(io); read!(io, Ref(MyStruct(NaN)))
Base.RefValue{MyStruct}(MyStruct(42.0))

iswritable — проверяет, поддерживается ли запись в указанный объект.

Details

Возвращает false, если запись в указанный объект ввода/вывода не поддерживается.

Примеры:

open("my_file.txt", "w") do io
    print(io, "Hello world!");
    iswritable(io)
end
true

open("my_file.txt", "r") do io
    iswritable(io)
end
false

rm("my_file.txt")

Чтение

read — выполняет чтение содержимого файла.

Details

По умолчанию read читает файл в бинарном режиме:

read("sample1.json")

#вывод
65-element Vector{UInt8}:
 0x7b
 0x0a
 0x20
 0x20
 0x20
    ⋮

Чтобы избежать представления в виде массива байт рекомендуется использовать аргумент представления. Например, функция read может принимать несколько аргументов, включая тип данных, в который нужно преобразовать содержимое файла (используем String):

read("sample1.json", String) #считывает содержимое файла sample1.json и возвращает его в виде строки

#вывод
"{\n    \"fruit\": \"Apple\",\n    \"size\": \"Large\",\n    \"color\": \"Red\"\n}"

Можно считать первый символ из файла и возвратить его в формате Char (символьный тип), используя аргумент Char:

read("sample1.json", Char)

#вывод
'{': ASCII/Unicode U+007B (category Ps: Punctuation, open)

Эта функция read(file_name::IOStream, number_of_bytes::Integer) выполняет чтение не более number_of_bytes байтов из потока file_name и возвращает массив Vector{ UInt8 }, содержащий считанные байты. Для получения потока из файла нужно открыть его для чтения. Например:

open("sample1.json", "r") #открываем файл для чтения

#вывод результата чтения
IOStream(<file sample1.json>)

read("sample1.json", 10) #читаем первые 10 байтов из файла

#вывод
10-element Vector{UInt8}:
 0x7b
 0x0a
 0x20
 0x20
 0x20
 0x20
 0x22
 0x66
 0x72
 0x75
Поток (stream) — это абстракция данных, которая представляет собой последовательность байт. Последовательность может быть прочитана или записана как из источников, так и в них. Например, текстовые файлы, сетевые соединения, память и т.д. Потоки также могут быть использованы для чтения данных из источника (ввод) или записи данных в него (вывод). Используйте:
  • flush — зафиксирует все записи, находящиеся в буфере в настоящий момент, в данном потоке.

  • close(stream) — закрывает поток ввода/вывода. Выполняет flush первоочередно.

  • closewrite(steam) — отключает половину записи полнодуплексного потока. Выполняет flush первоочередно. В базовый файл больше не будут записываться данные. Это поддерживается не всеми типами ввода/вывода.

Вы можете выполнять команды cmd, используя функцию read. Например, создадим команду date (выводит текущую дату и время):

#создаем команду, которая выводит текущую дату и время
cmd = `date`

read(cmd) #выводит результат как массив байтов

read(cmd, String) #выводит результат как строку
#вывод
"Thu Mar 28 07:44:58 UTC 2024\n"

read! — выполняет чтение двоичных данных из потока ввода/вывода или файла, заполняя матрицу данных.

Details

Функция read! используется для чтения данных из потока ввода/вывода или файла в предварительно выделенный буфер или массив. Она обычно используется для эффективного заполнения массива данными из внешнего источника без создания дополнительных временных массивов. Для получения потока из файла нужно открыть его для чтения. Например:

open("sample1.json", "r") #открываем файл для чтения

my_array = zeros(UInt8, 5) #создается массив из 5 элементов типа UInt8 заполненный нулями
#вывод
5-element Vector{UInt8}:
 0x00
 0x00
 0x00
 0x00
 0x00

read!("sample1.json", my_array) #считывает данные из sample1.json и заполняет ими массив my_array
#вывод
5-element Vector{UInt8}:
 0x7b
 0x0a
 0x20
 0x20
 0x20

readavailable — выполняет чтение доступных буферизованных данных из потока.

Details

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

Возвращаемый объем данных будет зависеть от реализации, например, он может зависеть от внутреннего выбора размера буфера. Вместо этого следует в целом использовать другие функции, такие как read.
IOS=open("sample1.json", "r") #открывает файл в режиме чтения и записывает его в содержимое буфер ввода/вывода IOS

readavailable(IOS) #считывает доступные данные из буфера ввода/вывода и возвращает их

readbytes! — выполняет чтение не более nb байтов из stream в b, возвращая количество считываемых байтов.

Details

Функция readbytes! считывает не более n байт из потока и записывает их в массив данных. Если n не задано, то считывает количество байт, равное длине массива. Затем она возвращает количество считанных байтов. Если в потоке доступно меньше байт, чем запрошено, будет считано только доступное количество байт.

IOS=open("sample1.json", "r") #открывает файл в режиме чтения и записывает его в содержимое буфер ввода/вывода IOS

buffer = Vector{UInt8}(undef, 5) #создается пустой массив buffer типа UInt8 длиной в 5 элементов

readbytes!(IOS, buffer) #считывает 5 байт из потока IOS и сохраняет их в массив buffer

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

readchomp — выполняет чтение полного объема файла как строки и удаляет один символ разрыва строки в конце (если есть).

Details

Функция readchomp эквивалентна chomp(read(x, String)).

write("my_file.txt", "Добро пожаловать в Engee.\n");

readchomp("my_file.txt")

#вывод
"Добро пожаловать в Engee."

readdir — возвращает имена в каталоге (dir) или текущем рабочем каталоге, если тот не указан.

Details

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

По умолчанию readdir сортирует список возвращаемых имен. Чтобы пропустить сортировку имен и получить их в том порядке, в котором они указаны в файловой системе, можно использовать readdir(dir, sort=false).

cd("/user") #переход на стартовую директорию user

readdir() #возвращает имена всех файлов в текущей директории (сейчас - "/user")
7-element Vector{String}:
 ".git"
 ".packages"
 ".project"
 "11.ngscript"
 "engee_commands.csv"
 "my_file.txt"
 "sample1.json"

readdir(join=true) #объединение возвращаемого имени с текущей директорией
7-element Vector{String}:
 "/user/.git"
 "/user/.packages"
 "/user/.project"
 "/user/11.ngscript"
 "/user/engee_commands.csv"
 "/user/my_file.txt"
 "/user/sample1.json"

readdir("my_dir") #возвращает имена всех файлов в каталоге my_dir
7-element Vector{String}:
 "RTFM-HISTORY.txt"
 "delay.html"
 "difference.pdf"
 "difference.xml"
 "littleendian.svg"
 "markdown_test.md"
 "mat.mat"

readdir("my_dir", join=true) #объединение возвращаемого имени с выбранной директорией (my_dir)
7-element Vector{String}:
 "my_dir/RTFM-HISTORY.txt"
 "my_dir/delay.html"
 "my_dir/difference.pdf"
 "my_dir/difference.xml"
 "my_dir/littleendian.svg"
 "my_dir/markdown_test.md"
 "my_dir/mat.mat"

readeach — возвращает итерируемый объект, дающий в результате read(io, T).

Details

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

io = IOBuffer("Добро пожаловать в Engee.\n Текст, который будет удален функцией.\n") #создается буфер ввода/вывода

for c in readeach(io, Char) #итерация по символам из потока до тех пор, пока не достигнет \n, после завершает итерацию
             c == '\n' && break
             print(c)
         end

#вывод
Добро пожаловать в Engee.

readline — выполняет чтение одной строки текста из заданного потока ввода/вывода или файла.

Details

При чтении из файла предполагается, что для текста используется кодировка UTF-8. Строки во входном конце с '\n' или "\r\n" или в конце входного потока. Также может использоваться аргумент keep. Если keep имеет значение false (по умолчанию), эти конечные символы новой строки удаляются из строки, прежде чем она будет возвращена. Если keep имеет значение true, они возвращаются как часть строки.

write("my_file.txt", "Добро пожаловать в Engee.\nТекст, который будет удален функцией.\n");

readline("my_file.txt")
"Добро пожаловать в Engee."

readline("my_file.txt", keep=true)
"Добро пожаловать в Engee.\n"

rm("my_file.txt") #удаляет файл my_file.txt

print("Enter your name: ")

your_name = readline() #откроет окно ввода имени пользователя
#введем имя, например Engee_User
"Engee_User"

readlines — выполняет чтение всех строк в потоке ввода/вывода или файле как векторных или строковых значений.

Details

Поведение аналогично повторяемому сохранению результата чтения readline с теми же аргументами и сохранению результирующих строк в виде векторных или строковых значений.

write("my_file.txt", "Добро пожаловать в Engee.\nТекст, который НЕ будет удален функцией.\n");

readlines("my_file.txt")
#вывод
2-element Vector{String}:
 "Добро пожаловать в Engee."
 "Текст, который НЕ будет удален функцией."

readlines("my_file.txt", keep=true)
2-element Vector{String}:
 "Добро пожаловать в Engee.\n"
 "Текст, который НЕ будет удален функцией.\n"

rm("my_file.txt") #удаляет файл my_file.txt

readuntil — выполняет чтение строки из потока ввода/вывода или файла (до заданного символа-разграничителя).

Details

Символ-разграничитель может быть UInt8, AbstractChar, строкой или вектором. Именованный аргумент keep определяет, включается ли символ-разграничитель в результат. Предполагается, что для текста используется кодировка UTF-8.

write("my_file.txt", "Добро пожаловать в Engee.\nТекст, который будет удален функцией.\n")

readuntil("my_file.txt", 'L')

readuntil("my_file.txt", '.', keep = true)
  "Добро пожаловать в Engee."

rm("my_file.txt")

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