Я знаю, что функцию fseek() можно использовать для вывода данных в определенное место в файле. Но мне было интересно, использую ли я fseek() для перемещения в середину файла, а затем вывожу данные. Будут ли новые данные перезаписывать старые данные? Например, если бы у меня был файл, содержащий 123456789, и я использовал fseek() для вывода новых данных после 5, файл бы содержал 12345newdata6789 или 12345newdata.
Можно ли использовать fseek() для вставки данных в середину файла? - С
Ответы (3)
Да, это позволяет вам это делать, и эти файлы называются «файлами произвольного доступа». Представьте, что у вас уже есть заданный файл (со структурой, но пустой), в этом случае вы можете заполнить нужные вам «слоты» или, если слот заполнен данными, вы можете перезаписать его.
typedef struct{
int number;
char name[ 20 ];
char lastname[ 20 ];
float score;
}students_t;
/* Supposing that you formatted the file already and the file is opened. */
/* Imagine the students are listed each one has a record. */
void modifyScore( FILE * fPtr ){
students_t student = { 0, "", "", 0.0 };
int nrecord;
float nscore;
printf( "Enter the number of the student:" );
scanf( "%d", &record )
printf( "Enter the new Score:" );
scanf( "%f", &nscore ); // this is a seek example so I will not complicate things.
/*Seek the file ( record - 1 ), because the file starts in position 0 but the list starts in 1*/
fseek( fPtr, ( record - 1 ) * sizeof ( students_t ), SEEK_SET );
/* Now you can read and copy the slot */
fread( fPtr, "%d%s%s%f", &student.number, student.name, student.lastname, &student.score );
/* Seek again cause the pointer moved. */
fseek( fPtr, ( record - 1 ) * sizeof ( students_t ), SEEK_SET );
student.score = nscore;
/*Overwrite his information, only the score will be altered. */
fwrite( &student, sizeof( student_t ), 1, fPtr );
}
Вот как это работает (изображение получено из Deitel-How to Program in C 6th Edition):
Запись данных в «середину» файла приведет к перезаписи существующих данных. Таким образом, у вас будет «12345newdata».
РЕДАКТИРОВАТЬ: Как упоминалось в комментариях ниже, следует отметить, что это перезаписывает данные без усечения остальной части файла. В качестве расширенной версии вашего примера, если вы написали
newdata
после 5
в файле, содержащем 1234567890ABCDEFG
, у вас будет 12345newdataCDEFG
, не 12345newdata
.
Вы, вероятно, знаете это, но fseek()
просто перемещает связанный индикатор положения и не диктует само по себе, будет ли выполняемая функция вывода перезаписывать или вставлять.
Вероятно, вы используете fwrite()
или какую-либо другую функцию вывода, и они перезапишут, дав вам "12345newdata" вместо вставленного варианта.
С другой стороны, вы можете свернуть свою собственную функцию вставки (я не думаю, что для этого существует стандартная функция stdio.h
) и вызвать ее после fseek()
, чтобы получить желаемую вставку.
Что-то вроде этого может быть достаточно:
insert(const void *ptr, size_t len, FILE *fp) {
char tmp[len];
size_t tmplen;
while (len) {
// save before overwriting
tmplen = fread(tmp, 1, sizeof(tmp), fp);
fseek(fp, -tmplen, SEEK_CUR);
// overwrite
fwrite(ptr, len, 1, fp);
// reloop to output saved data
ptr = tmp;
len = tmplen;
}
}
(Обработка ошибок на fread()
и fwrite()
опущена для многословия.)