reckfellENGINE

Чтение файлов и внешних ресурсов

Проверяемое чтение UTF-8, ошибки записи и загрузка PNG без редакторского импорта.

На этой странице

Текст: полный пример

Прикрепите FileDemo.cs к обычной Entity, соберите проект и запустите уровень. Скрипт создаёт user://io-demo/message.txt, записывает две строки UTF-8, читает их и выводит текст с File demo: Ok. Повторный запуск перезаписывает этот учебный файл.

WriteText() принимает путь, заданный вашим кодом. ReadText() возвращает пустую строку при ошибке и ограничивает чтение 1 МиБ. OutOfMemory здесь означает превышение лимита примера. Внутри using файл закрывается и при раннем return.

FileDemo.cs
C#
using System.Text;
using Reckfell;

public partial class FileDemo : Entity
{
    public const string Folder = "user://io-demo";
    public const string Note = Folder + "/message.txt";
    public const int MaxBytes = 1024 * 1024;
    private static readonly UTF8Encoding Utf8 = new(false, true);

    public static Error WriteNote(string text) => WriteText(Note, text);

    public static Error WriteText(string path, string text)
    {
        try
        {
            if (Utf8.GetByteCount(text) > MaxBytes)
                return Error.OutOfMemory;
        }
        catch (EncoderFallbackException)
        {
            return Error.InvalidData;
        }
        Error error = DirAccess.MakeDirRecursiveAbsolute(path.GetBaseDir());
        if (error != Error.Ok)
            return error;
        using var file = FileAccess.Open(path, FileAccess.ModeFlags.Write);
        if (file is null)
            return FileAccess.GetOpenError();
        return file.StoreString(text) ? file.GetError() : Error.FileCantWrite;
    }

    public static Error ReadText(string path, out string text)
    {
        text = "";
        using var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
        if (file is null)
            return FileAccess.GetOpenError();
        ulong length = file.GetLength();
        if (length > MaxBytes)
            return Error.OutOfMemory;
        byte[] bytes = file.GetBuffer((long)length);
        if ((ulong)bytes.Length != length)
            return Error.FileCorrupt;
        try
        {
            text = Utf8.GetString(bytes);
            return Error.Ok;
        }
        catch (DecoderFallbackException)
        {
            return Error.InvalidData;
        }
    }

    public override void _Ready()
    {
        Error error = WriteNote("Reckfell: привет\nSecond line");
        if (error == Error.Ok)
        {
            error = ReadText(Note, out string text);
            if (error == Error.Ok)
                ReckfellApi.Print(text);
        }
        ReckfellApi.Print($"File demo: {error}");
    }
}

Open() возвращает null при неудаче. Сразу получите GetOpenError(), прежде чем открывать другой файл в том же потоке. Проверяйте и открытие, и результат записи. Чтение отличает пустой файл от ошибки и отвергает некорректный UTF-8.

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

Режим открытия

РежимПоведение
ReadЧтение существующего файла
WriteСоздаёт файл или очищает существующий
ReadWriteЧитает и пишет существующий файл без начального обнуления
WriteReadСоздаёт либо очищает файл; затем доступны запись и чтение

Для добавления в существующий файл откройте ReadWrite и вызовите SeekEnd(). Если файла ещё нет, выберите Write. Перезапись с начала без усечения может оставить старый хвост.

Внешнее изображение

Скопируйте PNG в user://io-demo/preview.png. В уровне создайте TextureRect; рядом добавьте обычную Entity со скриптом ExternalPreview.cs и назначьте ей Target. Первая загрузка выполняется в _Ready(). Для повторной вызовите Reload() из своего обработчика кнопки. Error.Ok означает, что новая текстура назначена; при ошибке прежняя остаётся. Для видимости задайте TextureRect ненулевой размер. WithMipmaps нужен при уменьшении текстуры с подходящим фильтром или для использования в 3D.

ExternalPreview.cs
C#
using Reckfell;

public partial class ExternalPreview : Entity
{
    [Export] public string ImagePath { get; set; } = "user://io-demo/preview.png";
    [Export] public TextureRect Target { get; set; } = null!;
    [Export] public bool WithMipmaps { get; set; }

    public override void _Ready() => ReckfellApi.Print(Reload());

    public Error Reload()
    {
        if (!ReckfellObject.IsInstanceValid(Target))
            return Error.Unconfigured;
        if (!FileAccess.FileExists(ImagePath))
            return Error.FileNotFound;
        using var image = new Image();
        Error error = image.Load(ImagePath);
        if (error != Error.Ok)
            return error;
        if (WithMipmaps)
        {
            error = image.GenerateMipmaps();
            if (error != Error.Ok)
                return error;
        }
        ImageTexture texture = ImageTexture.CreateFromImage(image);
        Target.Texture = texture;
        return Error.Ok;
    }
}

Изображение из самого проекта загружайте через ResourceLoader.Load<Texture2D>(): экспорт может содержать импортированный ресурс вместо исходного PNG.

Другие внешние форматы

ДанныеAPI и следующий шаг
WAV, Ogg Vorbis, MP3AudioStreamWav.LoadFromFile(), AudioStreamOggVorbis.LoadFromFile(), AudioStreamMP3.LoadFromFile(); проверьте результат, затем назначьте AudioStreamPlayer.Stream и вызовите Play()
TTF / OTFСоздайте новый FontFile, загрузите через LoadDynamicFont(path) и проверьте файл и данные; одного Error.Ok недостаточно. Назначьте через тему или AddThemeFontOverride() после проверки
glTF / GLBGltfDocument.AppendFromFile(path, state) → проверка Error.Ok → GenerateScene(state) → AddChild() в главном потоке
ZIPZipReader.Open() → GetFiles() / FileExists() → ReadFile() → Close(); чтение записи не извлекает её на диск
Запись ZIPZipPacker.Open() → StartFile() → WriteFile() → CloseFile() → Close(); проверяйте каждый Error
Свой бинарный формат в C#byte[], System.Buffers.Binary.BinaryPrimitives и явное соглашение о порядке байтов; у byte[] нет методов Variant-массива decode_*

Для шрифта сначала проверьте существование файла, непустой размер и допустимый предел чтения. В текущей реализации LoadDynamicFont() сбрасывает состояние, читает байты, назначает их и возвращает Ok без проверки результата декодирования. Непустые FontFile.Data подтверждают только наличие данных: дополнительно проверьте нужные символы и отображение. Для повторной загрузки используйте новый ресурс, чтобы не сбросить уже используемый шрифт до проверки.

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

Диагностика

СбойПроверка
FileNotFoundФактический путь, регистр и существование файла
CantCreate, FileNoPermissionРодительская папка, права, место и доступ к файлу
FileCorruptКоличество прочитанных байтов не совпало с длиной
InvalidData в текстовом примереФайл не является корректным UTF-8
Шрифт вернул Ok, но текста нетФайл, лимит и данные FontFile.Data, пригодность формата и нужных символов; Ok сам не подтверждает декодирование
Ресурс работает в редакторе, но пропал в экспортеИспользуйте загрузчик импортированных ресурсов либо включите исходный внешний файл в поставку явно
Текстура загружена, но не виднаTarget, размер и видимость TextureRect; для 3D — материал и поверхность
Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.