2017-01-16 34 views
3

我試圖寫入使用write()功能(包含在<unistd.h>)的文件。該程序很簡單:當運行可執行文件時,我鍵入一條消息,然後將消息和我的用戶標識(Linux UID)保存到文件中。C和write()函數 - 文件正被寫入十六進制和書面int值是不正確的

$ ./notetaker "Hello" 

我期待的是,下面的值可以保存到文件:

1000 
Hello 

有兩個問題:

  • 我的文件正被寫入十六進制(當我打開它用崇高的文字,我能看到的是十六進制值)
  • 插入代表我的用戶ID的整數是不正確的

這是運行cat notes.txt當我得到的結果是:

� 
Hello 

當我打開notes.txt文件與崇高的文本,我可以閱讀以下資料:

e803 0000 0a48 656c 6c6f 0a 

前4個字節不等於「1000」。

爲什麼我的文件被保存與十六進制值?爲什麼數字不正確?

這是我的源代碼:

#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); 
} 

我使用一個Ubuntu 14.04忠實的塔爾羊(64),和我的版本的GCC 4.8.4是。另外,使用-Wall選項編譯時,不顯示警告。

+1

創建[mcve]。同時仔細檢查你的標籤。這個問題真的和C++有什麼關係嗎? – user2079303

+4

您的'write_uid'和'write_note'函數將數字寫入文件中,而不是以10爲基數的數字表示。您期望您可以在文件中找到字符串「1000」(基數爲10的數字表示)是不合理的,因爲你沒有代碼來編寫十個數字表示的文件。對於任何程序員來說,最重要的事情莫過於一個數字(比如兩個數字)和數字表示之間的差異(比如「two」是英文單詞或「2」是十進制數字,代表第二)。 –

+0

@ user2079303對不起,我的壞。我按照「最小,完整和可驗證」的要求編輯了代碼。 @DavidSchwartz,謝謝!仔細閱讀你的評論後,我可以看到我做錯了什麼。如你所說,數字本身(而不是它的表示)就在那裏:'e8 03 00 00'。我試圖按照原樣轉換數字,忘記了「小端」概念。當我轉換'3e8'時,我可以看到數字。你真的幫助了我。 –

回答

7

你的數值的1000值是第一個4個字節:e8 03 00 00

英特爾CPU爲小端的字節(不是半字節)必須重新排序在正常的從左到右的順序讀取它們,所以值變爲00 00 03 e8。丟棄前導零將使您以十六進制形式出現3e8,這實際上是十進制的1000。

你這裏的問題是,你正在寫從current_user_id的字節數,這是一個32位整數,給您的文件字符一個字符在內存中的順序。如果你想讓它作爲一個數字可讀,你將不得不使用你選擇的函數將它轉換爲字符串表示。阻力最小的路徑可能是使用fprintf()而不是write()

1

你必須格式化結果或其他明智的它會在原始的二進制寫入。使用fprintff ile printf ormatted)。或者,如果你對使用寫操作感到憤怒,那麼使用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