Системный вызов Read возвращает неверное количество байтов - PullRequest
1 голос
/ 30 мая 2019

Я пытаюсь реализовать fread, используя системный вызов read.Я использую файл JPEG, который составляет 4264394 байта, чтобы проверить мой код.Я использую пользовательский буфер и буфер класса файлов.Если пользовательский буфер больше буфера класса, то данные считываются непосредственно в пользовательский буфер.если пользовательский буфер меньше буфера класса файлов, то я сначала читаю данные в буфер файлов, как только он заполняется, я копирую их в буфер пользователя и перечитываю из файла.

Моя проблема заключается в том, что если я пытаюсь прочитать файл JPEG напрямую, задав для буфера класса файла меньшее значение, чем для буфера пользователя, файл будет считан непосредственно в буфер пользователя, а его размер будет правильным, как 4264394 байта.Тем не менее, если я попытался использовать буфер класса файлов, установив для него большее значение, чем пользовательский буфер, я получаю странное поведение, и чтение, кажется, неправильно считывает размер файла.Я использую буфер класса файлов 8192 байта и буфер пользователя 1024, поэтому буфер класса файлов ровно в 8 раз больше буфера пользователя.

size_t File::fread(void *ptr, size_t size, size_t nmemb) {

    off_t lseekk=0;
    lseekk = lseek(this->fd_, 0 , SEEK_CUR);
    cout << "lseek at begining is " << lseekk << endl;

    size_t bytes_read = 0;
    char* pChar;
    pChar = (char *) ptr;

    cout << "fread started" << endl;
    int flush;

    if (this->buf_state == WRITING) {
        flush = this->fflush(); // make sure to empty the buffer before starting to read
        if (flush == 0) {
            cout << "Flush successful" << endl;
        } else {
            cout << "Nothing to flush" << endl;
        }
    }

    this->buf_state = READING;

    if (nmemb < (size_t) bufsiz) {
        if (cur_buf_size == 0) {
            cout << "No data buffered" << endl;

            lseekk = lseek(this->fd_, 0 , SEEK_CUR);
            cout << "lseek before read is " << lseekk << endl;
            cur_buf_size = read(this->fd_, this->buf, this->bufsiz);

            lseekk = lseek(this->fd_, 0 , SEEK_CUR);
            cout << "lseek after read is " << lseekk << endl;

            if ((size_t)cur_buf_size < nmemb) { // in case no data buffered and the total size of file is less than nmemb
                nmemb = cur_buf_size;
            }


            if (cur_buf_size < 0) {
                perror("Error Reading File");
                exit(1);
            } else {
                cout << "file reading successful, number of bytes read is: " << cur_buf_size << endl;

                for (size_t i = 0; i < nmemb; i++) {
                    //char c;
                    char c = (char) buf[i];
                    pChar[i] = c;
                }
                buf = buf + nmemb;
                cur_buf_size = cur_buf_size - nmemb;


                return nmemb;
            }

        } else if ((cur_buf_size > 0) && (nmemb <= (size_t)cur_buf_size)) {
            cout << "enough data buffered, will not call read" << endl;
            for (unsigned i = 0; i < nmemb; i++) {
                char c = (char) buf[i];
                pChar[i] = c;
            }
            buf = buf + nmemb;
            cur_buf_size = cur_buf_size - nmemb;
            return nmemb;

        } else if (cur_buf_size > 0 && nmemb > (size_t)cur_buf_size) {
            int nmemb2 = nmemb;

            cout << "not enough data buffered, will call read to re-fill buffer" << endl;
            int remaining = cur_buf_size;

            buf = buf + remaining; // moving buffuer forward to start reading after the remianing chars

            cur_buf_size = read(this->fd_, this->buf, (this->bufsiz - remaining));
            if (cur_buf_size == -1){
              return remaining;
            }

            cur_buf_size = cur_buf_size + remaining;

            buf = buf - remaining; // reverting buffer again to where it was
            if ((size_t)cur_buf_size < nmemb) {
                nmemb2 = cur_buf_size;
                for (size_t i = 0; i < nmemb; i++) {
                    char c = (char) buf[i];
                    if (c == ' ') {
                        pChar[i] = ' ';
                    } else {
                        pChar[i] = c;
                    }
                }
                buf = buf + nmemb;
                cur_buf_size = cur_buf_size - nmemb;
                return nmemb2;
            }

            cout << "cur_buf_size is " << cur_buf_size << endl;
            for (size_t i = 0; i < nmemb; i++) {
                char c = (char) buf[i];
                if (c == ' ') {
                    pChar[i] = ' ';
                } else {
                    pChar[i] = c;
                }
            }
            buf = buf + nmemb;
            cur_buf_size = cur_buf_size - nmemb;
            return nmemb2;
        }
    } else {
        cout << "no double buffering, reading/writing data directly to/from the source/destination." << endl;
        bytes_read = read(this->fd_, ptr, nmemb);
        if (bytes_read < 0) {
            perror("Error Reading File");
            exit(1);
        }
        return bytes_read;
    }
    return bytes_read;
}

Это часть моей главной страницы, где я открываю файл и читаю его:

total_bytes_read = 0;
int chunk_size4 = 1024;
const char *name4 = "20190211_070835.jpg";
const char * mode4 = "r";
File * f4 = new File(name4, mode4);
char *ubuf4 = new char[chunk_size4];

while (true) {
bytes = f4->fread(ubuf4, 1, chunk_size4);
cout << bytes << endl;
if (bytes < 0) {
    perror("Error Reading File");
    exit(1);
}
if (bytes == 0) {
    cout << "Total Bytes Read is: " << total_bytes_read << endl;
    total_bytes_read=0;
    break;
} else {
    for (int i = 0; i < chunk_size; i++) {
        //cout << ubuf[i];
    }
    //cout << endl;
}
total_bytes_read = total_bytes_read + bytes;
}

Вот вывод:

 File opened r, File Descriptor is 6
 lseek at begining is 0
 fread started
 No data buffered
 lseek before read is 0
 lseek after read is 8192
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 8192
 fread started
 No data buffered
 lseek before read is 8192
 lseek after read is 16384
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 16384
 fread started
 No data buffered
 lseek before read is 16384
 lseek after read is 24576
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 24576
 fread started
 No data buffered
 lseek before read is 24576
 lseek after read is 32768
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 32768
 fread started
 No data buffered
 lseek before read is 32768
 lseek after read is 40960
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 40960
 fread started
 No data buffered
 lseek before read is 40960
 lseek after read is 49152
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 49152
 fread started
 No data buffered
 lseek before read is 49152
 lseek after read is 57344
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 57344
 fread started
 No data buffered
 lseek before read is 57344
 lseek after read is 65536
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 65536
 fread started
 No data buffered
 lseek before read is 65536
 lseek after read is 73728
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 73728
 fread started
 No data buffered
 lseek before read is 73728
 lseek after read is 81920
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 81920
 fread started
 No data buffered
 lseek before read is 81920
 lseek after read is 90112
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 90112
 fread started
 No data buffered
 lseek before read is 90112
 lseek after read is 98304
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 98304
 fread started
 No data buffered
 lseek before read is 98304
 lseek after read is 106496
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 106496
 fread started
 No data buffered
 lseek before read is 106496
 lseek after read is 114688
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 114688
 fread started
 No data buffered
 lseek before read is 114688
 lseek after read is 122880
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 122880
 fread started
 No data buffered
 lseek before read is 122880
 lseek after read is 131072
 file reading successful, number of bytes read is: 8192
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 131072
 fread started
 No data buffered
 lseek before read is 131072
 lseek after read is 134048
 file reading successful, number of bytes read is: 2976
 1024
 lseek at begining is 134048
 fread started
 enough data buffered, will not call read
 1024
 lseek at begining is 134048
 fread started
 not enough data buffered, will call read to re-fill buffer
 928
 lseek at begining is 134048
 fread started
 0
 Total Bytes Read is: 134048

Вывод показывает, что файл работает нормально, каждый раз считывая из файла 8192 байта, передавая их в пользовательский буфер в 8 кусках по 1024, а затем снова читая.в какой-то момент он решает прочитать только небольшой фрагмент, а затем EOF.

Я попытался запустить свой код на другом компьютере с Linux и получил другое количество прочитанных байтов.Есть идеи, что может быть не так?Это мой код или чтение системного вызова не работает?

В последний раз, когда я проверял, используя lseek в начале файла, lseek(this->fd_, 0 , SEEK_END) возвращает 4264394 байта, что означает, что ОС может видеть, что файл имеет размер 4264394 байта.

Хотите знать, что может быть не так?

...