Функции ввода/вывода
Открытие
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
Ключевое слово |
Описание |
По умолчанию |
---|---|---|
|
открыть для чтения |
|
По умолчанию, если ключевые слова не передаются, файлы будут открыты только для чтения. Возвращается поток для доступа к открытому файлу. Именованный аргумент lock
определяет, будут ли операции заблокированы для безопасного многопотокового доступа.
Альтернативный синтаксис открытия, в котором вместо пяти логических аргументов используется описатель режима, основанного на операциях со строками. Значения mode соответствуют значениям из fopen(3)
или Perl open
и
эквивалентны настройке следующих логических групп:
Режим |
Описание |
Ключевые слова |
---|---|---|
|
чтение |
нет
|
Примеры:
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
readlink
— возвращает целевое расположение, на которое указывает символьная ссылка path.
Details
Символьная ссылка — это специальный тип файла, который содержит путь к другому файлу или каталогу. Когда используется readlink
для символьной ссылки, она возвращает путь к файлу или каталогу, на который эта ссылка указывает. Например, если у вас есть символьная ссылка /path/to/link
, которая указывает на файл /path/to/target
, вызов readlink("/path/to/link")
вернет строку "/path/to/target"
, представляющую целевой файл или каталог, на который указывает символьная ссылка.
readlink(path::AbstractString) -> AbstractString
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 читайте в здесь.