Использование 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
читать до 11int
s (до 44 байт). Таким образом, первые 4 символа будут читаться какint
и хранится вarray[0]
и следующие 4 вarray[1]
,- Если вы проверили возврат
fread
он скажет вам, что на самом деле он читает только 2 элемента (так как содержимое имеет 11 байтов, он может читать только 2 элемента)int
s и последние 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);
// ..
Просто идея, а не код. Надеюсь, что это поможет;