Эквивалент open (O_WRONLY | O_CREAT) в GLib? - PullRequest
0 голосов
/ 21 мая 2018

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

Другими словами, в простом C я бы сделал:

int fd = open("output.bin", O_WRONLY | O_CREAT, 0666);
// I don't mind using O_RDWR, btw.

Я пытаюсь сделать что-то подобноес GLib GFile (часть GIO).Сначала я попробовал:

g_file_create(gfile, G_FILE_CREATE_NONE, NULL, NULL);

Но это не удалось, если файл уже существует.

Я вижу, что есть около 5 других функций , которые возвращают GFileOutputStream или GFileIOStream, но я не вижу того, который делает то, что я хочу.

Я что-то упускаю?

Нужно ли разбивать эту простую задачу на несколькомаленькие?(проверка существования файла; если существует, создайте, иначе откройте; все как-то обернуто в блокировку.)

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

Ответы [ 3 ]

0 голосов
/ 21 мая 2018

Я сделал это в два этапа.Я использовал предложение @ usr о проверке G_IO_ERROR_EXISTS.Мой код:

public class Downloader {

  public FileIOStream iostream;

  public OutputStream output { get { return iostream.output_stream; } }

  public void create_output_file() throws Error
  {
    File file = File.new_for_path("output.bin");
    try {
      // If file doesn't exist.
      iostream = file.create_readwrite(NONE);
    } catch (Error e) {
      if (e is IOError.EXISTS)
        // It exists.
        iostream = file.open_readwrite();
      else
        throw e;
    }
  }

}

(Здесь могут быть условия гонки, но в моем случае это не имеет значения.)

0 голосов
/ 09 июня 2018

Официальный ответ на вышестоящий поток состоит в том, что GIO, как высокоуровневый уровень абстракции, изначально не был предназначен для предоставления гарантий об атомарных операциях создания или открытия (как в случае O_CREAT), поэтому у вас есть два варианта:

  • Попробуйте создать файл и, если это не удастся выполнить с G_IO_ERROR_EXISTS, попробуйте открыть его;как в ваш ответ .
  • Создайте / откройте файл, используя open() с O_CREAT (как в вопросе), и передайте FD на g_unix_output_stream_new() создать новый GOutputStream, который оборачивает FD, и вы можете писать в него, как если бы он был возвращен g_file_create().

Обратите внимание, что g_unix_output_stream_new() неПереносим на не-Unix-платформы, но в вашем случае это не актуально.Этот второй вариант рекомендуется, если вы заботитесь об устранении условий гонки.

Обратите внимание, что существуют другие причины, чтобы избежать условия гонки: меньше кода, меньше системных вызовов (что означает лучшую производительность) и более читаемый код(если вы игнорируете внезапное присвоение имен open() API).

В будущем может быть поддержано выполнение этого напрямую с помощью метода на GFile: существует открытая проблема о поддержке в GLib.

0 голосов
/ 21 мая 2018

В документации Valadoc.org есть хорошие примеры, поэтому я не буду здесь кодировать рабочий пример.Я думаю, вам нужно GLib.File.new_for_path () и GLib.File.append_to ().Документация C для g_file_append_to () советует 'Получает выходной поток для добавления данных в файл.Если файл еще не существует, он создается.Обратите внимание, что append_to () принимает аргумент FileCreateFlags.Существует также асинхронная версия append_to () для Vala, append_to_async ().

Кстати, привязка Vala для open () есть в Posix VAPI.См. open (), O_WRONLY и O_CREAT на Valadoc.org.

...