3

I am trying to write into a file using the write() function (included in <unistd.h>). The program is simple: when running the executable, I type a message and then, the message and my user id (Linux UID) are saved into the file.

$ ./notetaker "Hello"

I was expecting that the following value could be saved into the file:

1000
Hello

There are two problems:

  • my file is being written in hexadecimal (when I open it using Sublime Text, all I can see are hexadecimal values)
  • the integer inserted representing my user id is not correct

This is the result that I'm getting when running cat notes.txt:

�
Hello

When I open the notes.txt file with Sublime Text, I can read the following data:

e803 0000 0a48 656c 6c6f 0a

The first 4 bytes are not equal to "1000".

Why is my file being saved with hexadecimal values? And why is the number incorrect?

This is my source code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

void write_uid(const int);
void write_note(const int, void *);

int main(int argc, char *argv[])
{
    char *buffer = (char *) malloc(100);
    if(buffer == NULL) exit(0);
    strcpy(buffer, argv[1]);

    char *filename = (char *) malloc(50);
    if(filename == NULL) exit(0);
    strcpy(filename, "notes.txt");

    int file_descriptor = open(filename, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR);
    if(file_descriptor == -1) exit(0);

    write_uid(file_descriptor);
    write_note(file_descriptor, buffer);

    if(close(file_descriptor) == -1) exit(0);

    printf("Your note has been saved successfully. \n");
    free(buffer);
    free(filename);

    return 1;
}

void write_uid(const int file_descriptor)
{
    int current_user_id = getuid();
    int uid_write_result_code = write(file_descriptor, &current_user_id, sizeof(current_user_id));
    int new_line_write_result_code = write(file_descriptor, "\n", 1);

    if(uid_write_result_code < 0 || new_line_write_result_code < 0)
        exit(0);
}

void write_note(const int file_descriptor, void *buffer)
{
    int note_write_result_code = write(file_descriptor, buffer, strlen( (char *) buffer ));
    int new_line_write_result_code = write(file_descriptor, "\n", 1);

    if(note_write_result_code < 0 || new_line_write_result_code < 0) 
        exit(0);
}

I'm using an Ubuntu 14.04 Trusty Tahr (x64), and my GCC version is 4.8.4. Also, when compiling using the -Wall option, no warning is shown.

4

2 回答 2

7

您的数值 1000 是前 4 个字节:e8 03 00 00.

Intel CPU 是 little-endian,字节(不是 nybbles)必须重新排序才能以正常的左右顺序读取它们,因此值变为00 00 03 e8. 删除前导零会使您3e8变成十六进制,实际上是十进制的 1000。

您的问题是您正在将current_user_id32 位整数中的字节按内存顺序逐个字符地写入文件。如果您希望它作为数字可读,则必须使用您选择的函数将其转换为字符串表示形式。阻力最小的路径可能是使用fprintf()而不是write()

于 2017-01-16T01:33:14.700 回答
1

您必须格式化结果,否则它将被写入原始二进制文件。使用fprintf文件打印格式 。或者,如果您要使用 write,则使用格式化整数sprintf以获取该整数的等效字符串表示形式,然后保存该字符串。

char str[20];
sprintf(str, "%i\n", current_user_id);
write(file_descriptor, str, strlen(str));
// no needto write \n, it's already included in str
于 2017-01-16T04:17:01.720 回答