Использование fread() для чтения текстового файла в буфер - почему значения в буфере не соответствуют значению ASCII каждого символа?

Во-первых, это не домашняя работа. Просто пытаюсь понять, почему я вижу то, что вижу на своем экране.

Материал ниже (моя собственная работа) в настоящее время берет входной файл и читает его как двоичный файл. Я хочу сохранить каждый прочитанный байт в массиве (для дальнейшего использования). Для краткости входной файл (Hello.txt) просто содержит "Hello World" без апострофов.

int main(int argc, char *argv[]) {

    FILE *input;
    int i, size;
    int *array;

    input = fopen("Hello.txt", "rb");
    if (input == NULL) {
        perror("Invalid file specified.");
        exit(-1);
    }

    fseek(input, 0, SEEK_END);
    size = ftell(input);
    fseek(input, 0, SEEK_SET);

    array = (int*) malloc(size * sizeof(int));
    if (array == NULL) {
        perror("Could not allocate array.");
        exit(-1);
    }
    else {
        input = fopen("Hello.txt", "rb");
        fread(array, sizeof(int), size, input);
        // some check on return value of fread?
        fclose(input);
    }

    for (i = 0; i < size; i++) {
        printf("array[%d] == %d\n", i, array[i]);
    }

Почему наличие оператора print в цикле for, как указано выше, приводит к тому, что вывод будет выглядеть так

array[0] == 1819043144
array[1] == 1867980911
array[2] == 6581362
array[3] == 0
array[4] == 0
array[5] == 0
array[6] == 0
array[7] == 0
array[8] == 0
array[9] == 0
array[10] == 0

имея это так

printf("array[%d] == %d\n", i, ((char *)array)[i]);

делает вывод похожим на это (десятичное значение ASCII для каждого символа)

array[0] == 72
array[1] == 101
array[2] == 108
array[3] == 108
array[4] == 111
array[5] == 32
array[6] == 87
array[7] == 111
array[8] == 114
array[9] == 108
array[10] == 100

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

Что касается связанного примечания, что произойдет, если входной файл, который я отправляю, не является текстовым документом (например, JPEG)?

Извините, это совершенно тривиальный вопрос, но я не могу понять, почему.

2 ответа

Поведение не удивительно

  • У вас есть файл, содержащий 11 символов. sizeof(char) это 1.
  • Теперь вы выделяете массив int с 11 инт. sizeof(int) очень вероятно, будет 4 на вашей машине
  • Вы учите fread читать до 11 ints (до 44 байт). Таким образом, первые 4 символа будут читаться как int и хранится в array[0] и следующие 4 в array[1],
    • Если вы проверили возвратfread он скажет вам, что на самом деле он читает только 2 элемента (так как содержимое имеет 11 байтов, он может читать только 2 элемента) ints и последние 3 оставшихся байта не могут быть успешно прочитаны как int).
  • Теперь вы перебираете массив и выводите число, которое является int Вы получаете наращивание первых 4 символов.
  • В вашем альтернативном решении вы делаете вид, что указываете на последовательность символов, поэтому индекс массива будет увеличиваться только на 1 байт.

Структура памяти в основном выглядит так:

array[0]
|       array[1]
|       |
1 2 3 4 5 6 7 8 9 10 11
| |
| ((char *)array)[1]
((char *)array)[0]

Ваш ftell возвращает текущее значение индикатора положения потока.

И он возвращает количество байт, которое имеет файл. И вы читаете файл как последовательность 4-байтовых int и, конечно, последним элементом будет 0. Для более подробной информации, вы читаете 4 байта размера из файла с байтами размера.

Ваш массив должен быть типа char.

Что-то вроде

char* array = malloc(sizeOfFile * sizeof(char));
if(array == NULL) {
  ...
}

fread(array, sizeOf(char), sizeOfFile, filePointer);
// ..

Просто идея, а не код. Надеюсь, что это поможет;

Другие вопросы по тегам