c_cpp “Linux的环境高级编程”作业2

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp “Linux的环境高级编程”作业2相关的知识,希望对你有一定的参考价值。

#include <fcntl.h>
#include <unistd.h>
#include <cstdarg>
#include <cstring>
#include <iostream>

using namespace std;

class FileOperator{
    //申请固定大小的读缓存和写缓存
    static const int READ_BUF_LEN = 4 * 1024;
    static const int WRITE_BUF_LEN = 4 * 1024;
    unsigned char readBuf[READ_BUF_LEN];
    unsigned char writeBuf[WRITE_BUF_LEN];
    //分别记录读缓存和写缓存对应文件中内容的起始偏移量和终止偏移量
    long startPositionOfReadBuf = -1;
    long startPositionOfWriteBuf = -1;
    long endPositionOfReadBuf = -1;
    long endPositionOfWriteBuf = -1;
    //记录打开文件的标识符
    int filePointer;
public:
    //打开文件并保存文件标识
    int fopen(const char *filePath, int oflag, ...){
        int filePointer;
        if((oflag == O_CREAT|O_WRONLY)||(oflag == O_CREAT|O_RDONLY)||(oflag == O_CREAT|O_RDWR)){
            va_list pvar;
            va_start(pvar, oflag);
            filePointer = open(filePath, oflag, va_arg(pvar, int));
            va_end(pvar);
        }
        else{
            filePointer = open(filePath, oflag);
        }
        this->filePointer = filePointer;
        return filePointer;
    }
    //在文件的当前偏移量处读取数据
    ssize_t fread(void *buf, size_t len){
        //如果写缓存有数据,就刷新到磁盘,重置写缓存
        if(endPositionOfWriteBuf > startPositionOfWriteBuf){
            long writeNum = write(filePointer, writeBuf, (size_t) (endPositionOfWriteBuf - startPositionOfWriteBuf));
            if(writeNum == -1) {
                return -1;
            }
            startPositionOfWriteBuf = -1;
            endPositionOfWriteBuf = -1;
        }
        //如果要读取的数据都在读缓存中,就直接返回数据
        long readStart = lseek(filePointer, 0, SEEK_CUR);
        if((readStart >= startPositionOfReadBuf)&&((long)(readStart + len) <= endPositionOfReadBuf)){
            memcpy(buf, &readBuf[readStart - startPositionOfReadBuf], len);
            return len;
        }
        else {
            //从磁盘上的文件读取数据并进行缓存
            unsigned long alreadyReadNum = 0;
            unsigned long toReadNum = len;
            //一次读取的数据可能超过缓存大小,这时缓存的数据是要读取数据的最后一块不超过缓存大小的数据
            while (toReadNum > 0) {
                startPositionOfReadBuf = lseek(filePointer, 0, SEEK_CUR);
                long readNum = read(filePointer, readBuf, (size_t) READ_BUF_LEN);
                endPositionOfReadBuf = startPositionOfReadBuf + readNum;
                if (readNum == -1) {
                    return -1;
                } else if (readNum == 0) {
                    break;
                } else {
                    unsigned long realReadNum = toReadNum < readNum ? toReadNum : (unsigned long) readNum;
                    memcpy(buf + alreadyReadNum, readBuf, (size_t) realReadNum);
                    toReadNum -= realReadNum;
                    alreadyReadNum += realReadNum;
                }
            }
            return alreadyReadNum;
        }
    }
    //在文件的当前偏移量处写入数据
    ssize_t fwrite(void *buf, size_t len){
        long writeStart = lseek(filePointer, 0, SEEK_CUR);
        //如果写入位置与读缓存有重合,则同时要修改读缓存内容
        if((writeStart < endPositionOfReadBuf)&&(writeStart + len > startPositionOfReadBuf)){
            long startPosition = writeStart > startPositionOfReadBuf ? writeStart : startPositionOfReadBuf;
            long endPosition = (writeStart + (long)len < endPositionOfReadBuf)?(writeStart + (long)len):endPositionOfReadBuf;
            memcpy(readBuf + startPosition - startPositionOfReadBuf, buf + startPosition - writeStart,
                   (size_t) (endPosition - startPosition));
        }
        //如果要写入数据对应的位置包含在已有写缓存中,则直接对写缓存进行修改
        if((writeStart >= startPositionOfWriteBuf)&&((long)(writeStart + len) <= endPositionOfWriteBuf)){
            memcpy(&writeBuf[writeStart - startPositionOfWriteBuf], buf, len);
            return len;
        }
        else {
            //否则将原有缓存数据刷新到磁盘,然后写缓存保存新数据
            unsigned long alreadyWrittenNum = 0;
            unsigned long toWriteNum = len;
            while (toWriteNum > 0) {
                long writeNum = write(filePointer, writeBuf, (size_t) (endPositionOfWriteBuf - startPositionOfWriteBuf));
                if(writeNum == -1) {
                    return -1;
                }
                unsigned long realWriteNum = toWriteNum < WRITE_BUF_LEN ? toWriteNum : (unsigned long) WRITE_BUF_LEN;
                memcpy(writeBuf, buf + alreadyWrittenNum, (size_t) realWriteNum);
                startPositionOfWriteBuf = lseek(filePointer, 0, SEEK_CUR);
                endPositionOfWriteBuf = startPositionOfWriteBuf + realWriteNum;
                toWriteNum -= realWriteNum;
                alreadyWrittenNum += realWriteNum;
            }
            return alreadyWrittenNum;
        }
    }
    //修改当前文件偏移量
    __off_t fseek(__off_t offset, int whence){
        //修改之前将写缓存刷新到磁盘并重置
        long writeNum = write(filePointer, writeBuf, (size_t) (endPositionOfWriteBuf - startPositionOfWriteBuf));
        if(writeNum == -1) {
            return -1;
        }
        startPositionOfWriteBuf = -1;
        endPositionOfWriteBuf = -1;
        return lseek(filePointer, offset, whence);
    }
    //关闭文件
    int fclose(){
        //关闭之前要先将写缓存刷新到磁盘,然后重置读写缓存
        long writeNum = write(filePointer, writeBuf, (size_t) (endPositionOfWriteBuf - startPositionOfWriteBuf));
        if(writeNum == -1) {
            return -1;
        }
        startPositionOfReadBuf = -1;
        startPositionOfWriteBuf = -1;
        endPositionOfReadBuf = -1;
        endPositionOfWriteBuf = -1;
        return close(filePointer);
    }
};
int main() {
    char writeBuf[1000] = "234v4wqrtmq24n";
    char readBuf[1000] = {'\0'};
    FileOperator* fileOperator = new FileOperator();
    int filePointer = fileOperator->fopen("/home/developerdong/task1.txt", O_RDWR);
    cout << fileOperator->fwrite(writeBuf, strlen(writeBuf)) << endl;

    fileOperator->fread(readBuf, 11);
    cout << readBuf << endl;

    fileOperator->fseek(0, SEEK_SET);
    fileOperator->fread(readBuf, 11);
    cout << readBuf << endl;
    fileOperator->fclose();
    delete(fileOperator);
}

以上是关于c_cpp “Linux的环境高级编程”作业2的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp “Linux的环境高级编程”作业1

c_cpp 给定Ñ个作业的集合{J1,J2,......,JN}。每个作业必须先由机器1处理,然后由机器2处理。作业籍需要机器Ĵ的处理时间为TJI。对于一个确定的作业调度,设Fji是作业我在

c_cpp 给定Ñ个作业的集合{J1,J2,......,JN}。每个作业必须先由机器1处理,然后由机器2处理。作业籍需要机器Ĵ的处理时间为TJI。对于一个确定的作业调度,设FJI是作业我在

c_cpp Ñ个作业{1,2,...,N}要在由2台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工.M1和M2加工作业我所需的时间分别为AI和璧

c_cpp 【分支限界法】批处理作业调度

c_cpp 【动态规划】流水作业调度【3.9】