Как сделать fsync на ofstream?

Итак, есть несколько уровней проблем с тем, что вы пытаетесь сделать.

Вы говорите «практичность - не аргумент», и это нормально, но позвольте мне отметить, что Long.MAX_VALUE действительно превышает количество атомов на земле, так что вероятность того, что вы получите больше записей, чем от База данных действительно мала. Не говоря уже о том, что вы продолжаете собирать эти данные в список, чтобы вы могли столкнуться с проблемами памяти и в своем собственном приложении.

Итак, во-вторых, семантика limit() заключается в том, что она накладывает фиксированное ограничение на число записей, а «бесконечность» не является фиксированным пределом; следовательно, limit() просто не то, что вы ищете.

В-третьих, вы, кажется, ищете способ обойти это, поэтому у нас есть шаблон, который вы можете использовать, и это поддерживает ваш собственный счетчик. То, что вы хотите, это что-то вроде AtomicBigInteger, которого нет в JDK , но показано здесь .

Итак, вы должны создать Predicate, подобный этому

class BelowValue implements Predicate {
    BigInteger limit = BigInteger.ZERO;
    AtomicBigInteger counter = new AtomicBigInteger();

    public BelowValue(BigInteger limit) {
        this.limit = limit;
    }        
    public BelowValue() {}

    public boolean test(T ignored) {
        // short circuit on zero
        if (BigInteger.ZERO.compareTo(limit) == 0) { return true; }

        // check actual condition
        return  counter.incrementAndGet().compareTo(limit) > 0;
    }
}

, и затем вы можете использовать его в своем потоке с (Java 8)

Predicate filter = new BelowValue<>(limit);
return stream
    .filter(filter)
    .boxed()
    .collect(Collectors.toList());

Примечание. однако filter - это , а не - операция с коротким замыканием, поэтому, если у вас бесконечный поток, он не прекратится (и будет очень неэффективным, если ваш поток намного длиннее предельного размера). [1118 ]

Java 9 takeWhile имеет короткое замыкание, поэтому вы можете заменить его на filter в приведенном выше примере.

19
задан Vik 25 March 2009 в 20:56
поделиться

2 ответа

К сожалению, просматривая стандарт нет ничего обеспеченного basic_filebuf или любой из basic_[io]?fstream шаблоны классов, чтобы позволить Вам извлекать базовый дескриптор файла ОС (в пути, который fileno() делает для C stdio ввод-вывод).

И при этом нет open() метод или конструктор, который берет такой дескриптор файла в качестве параметра (который позволил бы Вам открывать файл с помощью другого механизма и записывать дескриптор файла).

Существует basic_ostream::flush(), однако я подозреваю, что это на самом деле не звонит fsync() - Я ожидаю это, как fflush() в stdio это только удостоверяется, что буферы библиотеки времени выполнения пространства пользователя сбрасываются, означая, что ОС могла все еще буферизовать данные.

Так короче говоря, кажется, нет никакого способа сделать это портативно.:(

Что сделать? Мое предложение состоит в том, чтобы разделить на подклассы basic_filebuf<C, T>:

template <typename charT, typename traits = std::char_traits<charT> >
class my_basic_filebuf : public basic_filebuf<charT, traits> {
    ....

public:
    int fileno() { ... }
    ....
};

typedef my_basic_filebuf<char> my_filebuf;

Для использования его можно создать ofstream с помощью конструктора по умолчанию затем присвойте новый буфер с rdbuf():

my_filebuf buf;
buf.open("somefile.txt");

ofstream ofs;
ofs.rdbuf(&buf);

ofs << "Writing to somefile.txt..." << endl;
int fd = static_cast<my_filebuf*>(ofs.rdbuf())->fileno();

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

5
ответ дан 30 November 2019 в 05:01
поделиться

Вы не можете портативно сделать fsync() на дескрипторе файла открываются для чтения, вообще. В Linux, fsync() документируется как генерирующий EBADF, если дескриптор не находится в режиме записи.

2
ответ дан 30 November 2019 в 05:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: