LINUX.ORG.RU

Какой самый быстрый способ прочитать значение из файла

 ,


0

2

Всем привет!

Допустим у меня есть файлы содержащие одно единственное значение, например md5 другого файла, или файл '/sys/class/power_supply/battery/online', который содержит только 0 или 1 в зависимости от состояния устройства...

Какой самый простой и правильный способ получить эти значения в программе?

Например я сейчас читаю значение таким образом, но мне не нравится как это выглядит...

static int
battery_online () {
    FILE *f = fopen ("/sys/class/power_supply/battery/online", "r");
    if (!f) {
        perrmsg ("fopen: '/sys/class/power_supply/battery/online'");
        return 0;
    }

    char str[32];
    int status = 0;
    if (fgets (str, sizeof (str), f))
        status = atoi (str);
    else
        perrmsg ("fail on read '/sys/class/power_supply/battery/online'");
    fclose (f);
    return status;
}

Покритикуйте? Как правильней сделать? Спасибо)

Касаемо /sys/class/power_supply/battery/online будет достаточно fgetc() самое то, читать просто 1 «символ» с файла

Deleted
()

Тут вон даже бенчили fread и mmap https://stackoverflow.com/questions/3002122/fastest-file-reading-in-c

Как правильней сделать?

Правильных способов не существует, есть только тот который лично ты считаешь оправданным по тем или иным причинам.

Deleted
()

Как правильней сделать?

$ perl -e 'open FILE, "<", "/sys/class/power_supply/battery/online"; my $line = <FILE>'


кинешь питик на сотик - номер в личке.

mos ★★☆☆☆
()

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

mittorn ★★★★★
()
Ответ на: комментарий от mittorn

по идее эти виртуальные файлы не должны запоминать позицию

Нет, они обязаны запоминать позицию, иначе семантика файлов поломается.

выполнять read

Можно вызывать pread() вместо lseek()+read().

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

Нет. Mmap там не работает, а если бы работал - замапить медленнее, чем прочитать один байт.

anonymous
()
Ответ на: комментарий от i-rinat

ну так надо смотреть реализацию в ядре. семанитика файлов на уровне реализации в драйвере этих самых read, write. Причём реализация твм максимально простая. Оно обязано разве что не выйти за границы буффера. уверен, что seek на таком файле выдаст ошибку.

mittorn ★★★★★
()
Последнее исправление: mittorn (всего исправлений: 1)
Ответ на: комментарий от mittorn

seek на таком файле выдаст ошибку.

Нет, не выдаёт. Но эффект интересный.

i-rinat ★★★★★
()
#include <stdio.h>
#include <assert.h>

int batstat()
{
    char   stat = 0;
    FILE * file = NULL;
    assert(fopen("/sys/class/power_supply/battery/online","r"));
    fread(&stat, 1, 1, file);
    fclose(file);
    return (stat == '0');
}

int main(int argc, char *argv[])
{
    printf("%d\n",batstat());
    return 0;
}

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

Deleted
()
Ответ на: комментарий от Deleted

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

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

cPunk ★★
()
Последнее исправление: cPunk (всего исправлений: 1)
Ответ на: комментарий от cPunk

Так он же хочет быстро, вдруг его аудитория увлекается втык-вытыком батарейки их ноута на скорость.

Deleted
()
Ответ на: комментарий от Sorcerer

Зато надёжно :D Но ты бы лучше проголосовал кодом, посоревновались бы

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)

Замени этой файл на fifo и читай из него только изменения. Вряд ли писатель заметит. Правда root нужен. И другие читатели могут поломаться.

Я так понял этот твой battery_online вызывается постоянно среди миллиарда других такого типа проверок, и поэтому ты ссышь из-за производительности?

Тогда вынеси открытие файла вовне. До пересоздания дескриптор вроде не меняется. И закрывать файл не нужно. Просто seek. И не вызывай в каждом цикле - отслеживай изменения (времени, например). И значение в int не нужно конвертить. Сравнивать на неравенство можно и строки. А в данном случае символы (их и нужно читать).

Ну и обычные оптимизации память -> скорость: сделай локальные переменные статическими.

anonymous
()

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

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

или файл '/sys/class/power_supply/battery/online'

С этими вообще не парься, тут нет обращений к файловой системе, и никакой «хитрый» способ чтения работать не будет, только системный вызов read и его всевозможные обертки типа fgets

annulen ★★★★★
()

char buffer[1]
int status;
int fd = open()
if (read(fd, buffer, sizeof(buffer)) < 0) return EXIT_FAILURE;
if (buffer[0] == '0') status = 0 else status = 1
close(fd)

reprimand ★★★★★
()
Последнее исправление: reprimand (всего исправлений: 1)
#define BATTERY_FILE_NAME "/sys/class/power_supply/battery/online"

static int
battery_online () {
    int status = 0;
    char c;
    int fd;

    fd = open (BATTERY_FILE_NAME, O_RDONLY);
    if (fd < 0) {
        perrmsg ("open: " BATTERY_FILE_NAME);
        return -1;
    }

    if (read(fd, &c, 1) != 1) {
        perrmsg ("fail on read " BATTERY_FILE_NAME);
        c = -1;
    } else {
        c -= '0';
        if (c != 0 && c != 1)
           c = -1;
    }

    close(fd);

    return c;
}
ttnl ★★★★★
()
Последнее исправление: ttnl (всего исправлений: 3)
Ответ на: комментарий от Deleted

man mmap, но это не точно.

mmap для чтения одного символа медленнее разового read.

ttnl ★★★★★
()
Последнее исправление: ttnl (всего исправлений: 1)
Ответ на: комментарий от Deleted

assert(fopen(«/sys/class/power_supply/battery/online»,«r»));

зачем мозг, assertдрочерство его заменит, в итоге прога ипанется только потому что на компе нет батареи... LOL

anonymous2 ★★★★★
()
Последнее исправление: anonymous2 (всего исправлений: 1)
Ответ на: комментарий от Deleted

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

и вообще читаешь fread ты из черной дыры если до сих пор и не понял...

сделать код красиво не означает правильно))

anonymous2 ★★★★★
()
Последнее исправление: anonymous2 (всего исправлений: 2)
Ответ на: комментарий от anonymous2

Я аще не программист, мне можно даже так! :D

подумай, что будет в продакшне дальше, если нет батареи…

#define NDEBUG )))))))))))

и вообще читаешь fread ты из черной дыры

Хм

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Блин, отвлёкся

подумай, что будет в продакшне дальше, если нет батареи…

#define NDEBUG ))))))))))) и буууум

или/и

#undef  assert
#define assert(exe) exe 
Deleted
()
Ответ на: комментарий от Deleted

вот твой код

FILE * file = NULL;
assert(fopen("/sys/class/power_supply/battery/online","r"));
fread(&stat, 1, 1, file);

неужели не понятно, креш будет ты при любых вариантах NDEBUG и assert абсолютно тут не информативен...

anonymous2 ★★★★★
()
Последнее исправление: anonymous2 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.