Как записать в файл с помощью системного вызова записи и прочитать их точно так, как написано?

Как я могу записать в файл int, float или другие типы, используя системный вызов записи UNIX? Я хочу сделать это без использования каких-либо функций lib, таких как fprintf или fwrite.

Я хочу использовать файловый дескриптор, а не FILE*.

После повторного открытия файл должен быть прочитан точно так, как он записан, без необходимости знать, какого размера читать.


person Sam    schedule 01.04.2013    source источник
comment
pubs.opengroup.org/onlinepubs/009695399/functions/write.html   -  person teppic    schedule 01.04.2013
comment
Откройте файловый дескриптор, создайте буфер и вызовите write. с чем у тебя проблемы?   -  person squiguy    schedule 01.04.2013
comment
@squiguy Разве нет простого способа сделать это?   -  person Sam    schedule 01.04.2013
comment
@SAM: Как вы думаете, есть ли способ проще??   -  person Aswin Murugesh    schedule 01.04.2013
comment
Вы хотите, чтобы файл был доступен для чтения людям? Вы хотите, чтобы файл был доступен для чтения другим компьютерам, которые используют другой порядок байтов для int и float? Вы хотите, чтобы файл был доступен для чтения на других компьютерах, которые используют разные форматы/кодировки для int и float?   -  person Eric Postpischil    schedule 01.04.2013
comment
@AswinMurugesh Вы поняли мой вопрос?   -  person Sam    schedule 02.04.2013
comment
@EricPostpischil Доступно для чтения людьми   -  person Sam    schedule 02.04.2013
comment
@squiguy Хорошо, хорошо, я понял. Вы говорили буферу, адрес которого является вторым аргументом для записи. Я думал, ты говоришь мне создать еще один буфер и что-то с ним сделать. Извини.   -  person Sam    schedule 02.04.2013
comment
@SAM: Чтобы написать int или float, которые могут быть прочитаны людьми, вы должны преобразовать их в число, а затем написать символы этого числа. Для float, если внутреннее представление использует другую базу (например, двоичную), чем числовое (например, десятичное), то для правильного выполнения требуется много работы.   -  person Eric Postpischil    schedule 02.04.2013
comment
Точно! @EricPostpischil, сделай это ответом, и я приму его.   -  person Sam    schedule 02.04.2013
comment
@EricPostpischil, не могли бы вы сказать, какая работа потребуется для int?   -  person Sam    schedule 02.04.2013
comment
Столько гнева на вопросы C на SO, лол. Напугай их до Явы!   -  person SSH This    schedule 15.11.2013


Ответы (2)


Это настолько просто, насколько это возможно (обратите внимание, что stdio.h включено только для printf; чтение/запись работает без него):

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main()
{
    // Open file with write permission (create if doesn't exist).
    int fd = open("float.txt", O_CREAT | O_WRONLY);
    float val = 1.5f;
    if (fd != -1) {
        write(fd, &val, sizeof(val));
        close(fd);
    }

    // Test read.
    fd = open("float.txt", O_RDONLY);
    float new_val;
    if (fd != -1) {
        read(fd, &new_val, sizeof(new_val));
        printf("new_val = %f\n", new_val);
        close(fd);
    }
    return 0;
}
person Jengerer    schedule 01.04.2013
comment
Я уверен, что мы можем предположить, что вы пропустили проверку ошибок, по крайней мере, для системных вызовов read и write для простоты чтения, не так ли? ;-) - person alk; 01.04.2013

Как установлено в комментариях, проблема заключается в том, чтобы преобразовать число в десятичное число, а не использовать вызов write.

Чтобы написать целое число или число с плавающей запятой, которое может быть прочитано людьми, вы должны преобразовать его в число, а затем написать символы этого числа. Для числа с плавающей запятой, если внутреннее представление использует другую базу (например, двоичную), чем числовое (например, десятичное), то для правильного выполнения требуется много работы. Я бы рекомендовал либо использовать существующий открытый исходный код, либо научную статью по теме.

Код для преобразования int в десятичное число довольно прост:

#include <stdlib.h> //  For size_t.


/*  IntToString converts the int x to a decimal numeral, which is written to s.
    No terminal null character is written.  The number of characters written is
    returned.  s MUST point to space with enough room for the numeral,
    including a leading '-' if x is negative.
*/
size_t IntToString(char *s, int x)
{
    //  Set pointer to current position.
    char *p = s;

    //  Set t to absolute value of x.
    unsigned t = x;
    if (x < 0) t = -t;

    //  Write digits.
    do
    {
        *p++ = '0' + t % 10;
        t /= 10;
    } while (t);

    //  If x is negative, write sign.
    if (x < 0)
        *p++ = '-';

    //  Remember the return value, the number of characters written.
    size_t r = p-s;

    //  Since we wrote the characters in reverse order, reverse them.
    while (s < --p)
    {
        char t = *s;
        *s++ = *p;
        *p = t;
    }

    return r;
}


#include <stdio.h>  //  For printf.


//  Demonstrate IntToString.
static void Demonstrate(int x)
{
    char buf[100];
    size_t n = IntToString(buf, x);
    printf("IntToString(%d) = %.*s.\n", x, (int) n, buf);
}


#include <limits.h> //  For INT_MIN and INT_MAX.


int main(void)
{
    Demonstrate(0);
    Demonstrate(1);
    Demonstrate(9);
    Demonstrate(10);
    Demonstrate(INT_MAX-1);
    Demonstrate(INT_MAX);
    Demonstrate(-1);
    Demonstrate(-9);
    Demonstrate(-10);
    Demonstrate(INT_MIN+1);
    Demonstrate(INT_MIN);

    return 0;
}
person Eric Postpischil    schedule 02.04.2013
comment
@ Эрик, проблема в том, что люди из Google приходят сюда в поисках того, как записать в файл с помощью системного вызова. - person Tomáš Zato - Reinstate Monica; 07.04.2015