11.10.2015

Linux C open(), close(), read(), write(), lseek()

這一系列的文章已經快要進入到尾聲了....這一次要紀錄的是比較低階的I/O: open(), close(), read(), write(), lseek()

同樣地,可以把之前的範例f_ctrl.c (Linux C fopen(), fclose(), fread(), fwrite(), fseek(), ftell(), rewind())拿來修改一下,然後把註解移除掉;
// ctrl.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    int fd0 = 0, fd1 = 0;
    char szTemp[4];
    off_t pos = 0L;

    fd0 = open("Read.TXT", O_RDONLY);
    if (fd0 == -1) {
        perror("Open \"Read.TXT\" failed!! \n");
        close(fd0);
        return 1;
    }
    fd1 = open("Write.TXT", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (fd1 == -1) {
        perror("Open \"Write.TXT\" failed!! \n");
        close(fd1);
        return 1;
    }

    memset(&szTemp, '\0', sizeof(char) * 4);
    pos = lseek(fd0, 5L, SEEK_SET);
    read(fd0, (void *)&szTemp, sizeof(char) * 4);
    write(fd1, (void *)&szTemp, sizeof(char) * 4);
    szTemp[4 - 1] = '\0';
    printf("Position0: %ld, %s \n", pos, (char *)szTemp);

    memset(&szTemp, '\0', sizeof(char) * 4);
    pos = lseek(fd0, -1L, SEEK_CUR);
    read(fd0, (void *)&szTemp, sizeof(char) * 4);
    write(fd1, (void *)&szTemp, sizeof(char) * 4);
    szTemp[4 - 1] = '\0';
    printf("Position1: %ld, %s \n", pos, (char *)szTemp);

    memset(&szTemp, '\0', sizeof(char) * 4);
    pos = lseek(fd0, -6L, SEEK_END);
    read(fd0, (void *)&szTemp, sizeof(char) * 4);
    write(fd1, (void *)&szTemp, sizeof(char) * 4);
    szTemp[4 - 1] = '\0';
    printf("Position2: %ld, %s \n", pos, (char *)szTemp);

    pos = lseek(fd0, 0L, SEEK_END);
    printf("The last position: %ld \n", pos);
 
    pos = lseek(fd0, 0L, SEEK_SET);
    printf("The first position: %ld \n", pos);

    close(fd0);
    close(fd1);

    return 0;
}
首先,要澄清一下,這個範例完全沒有實務上的意義,因為低階的存取,並不是這樣用。寫這樣的範例只是呈現這些函式的用法而已。

低階IO裡面,並沒有類似ftell()和rewind()的函式;不過還是有其他的方法可以達成。

先看一下執行的結果:


Position的位置都不一樣,是因為在ctrl.c中的lseek()所回傳的是「現在的位置」;而f_ctrl.c中的ftell()回傳的是「執行過fread()之後的位置」;

那麼fread()執行過的單位大小是多少?? 就是sizeof(char) * 4,所以兩者之間的執行結果都是差4 (但完全不影響Write.TXT的內容)。

假如,"The last position: "所顯示的是22,而不是21,這是換行字元 ('\n')CRLF (註)的問題,表示你的"Read.TXT"檔案內容是在Windows下產生的,因為Windows下的換行字元是以0x0D, 0x0A的方式呈現,若是在Linux環境下就只有0x0A

最后,還是附上各個函式的原型宣告;其中比較複雜的是open()的第2個和第3個參數,有興趣的可以自行詳細研究。

int open(char *pathname, int flags);
int open(char *pathname, int flags, mode_t mode);

int close(int fd);

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, void *buf, size_t count);

off_t lseek(int fildes, off_t offset, int whence);

PS:CRLF, CR/LF, Carriage Return / Line Feed, 回車 / 換行, 0x0D / 0x0A, 這是打字機 (Typewriter)的用語。

沒有留言:

張貼留言