2012-04-20 2 views
3

У меня есть внутренний файл, который может быть добавлен только после добавления каждого добавочного символа \n. Но теоретически возможно, что добавление к файлу не выполняется, и оно становится поврежденным. Вот почему каждый раз при открытии файла я хочу найти его последнюю действительную, после последней EOL, позицию. Этот код будет делать:Как удалить содержимое файла после последнего EOL?

// Not using ios::app instead of ios::ate | ios::out because it will 
// put print pointer to the EOF every time before writing. 
fstream file(name.c_str(), ios::binary | ios::ate | ios::out | ios::in); 
if(!file.is_open()) { 
    cerr << "Error in oppening file " << name << endl; 
    exit(EXIT_FAILURE); 
} else { 
    while(0 != file.tellp()) //if file is not empty 
    { 
     file.seekg(-1, ios_base::cur); 
     if(0 == file.tellg() || file.get() == '\n') { 
      break; 
     } 
     file.seekg(-1, ios_base::cur); 
    } 
    file.seekp(of.tellg()); 
} 
//{1} 
//Use file for appending to... 

Но это не будет работать хорошо, если длина части, которая должна быть добавлена ​​в файл ниже, чем длина части, начиная с последнего символа EOL в файле. Поэтому в позиции {1} я хочу удалить содержимое файла, начиная с file.tellp() до конца.

Как я могу это сделать?

ответ

1

Существует нет портативного способа сделать это (см. Джеймс Канзе гораздо лучший ответ для более полного объяснения).

Если вы находитесь в системе POSIX, вы можете использовать ftruncate (см. here), чтобы установить длину файла на определенную длину. Я не знаю эквивалента C++ (см. this question для получения дополнительной информации)

+0

'ftruncate' - это только Unix. И он не принимает поток или 'ФАЙЛ * 'как аргумент. –

+0

Это не идеал (как я уже сказал, я не знаю ни одного C++). Я не понимал, что это только команда POSIX. В Windows, похоже, вам нужно использовать '_chsize_s' для достижения того же. –

+0

Под Windows соответствующей функцией будет 'SetEndOfFile'. Оба требуют, чтобы дескриптор системы работал (а не 'filebuf', а не' FILE * ', поэтому ни C++, ни C). –

1

Вы не можете, портативно. Различные системы имеют разные способы делать это , но обычно это только в дескрипторе системного файла. Единственный гарантированный способ сокращения файла - скопировать его в другой файл, а не копировать то, что вы не хотите, а затем удалить оригинал и переименовать новый файл.

Если это текстовый файл (не двоичный), и вы находитесь под окнами, запись 0x1A в позиции может работать. Однако нет ничего подобного в Unix, .

В вашем случае недостаточно просто переписать конец. Если худшее подходит к худшему, и то, что вам нужно добавить, недостаточно для того, чтобы переписать конечные данные, вы можете попробовать переписать его с чем-то нечетким и легко узнаваемым, например '\0'. (Формально писать вещи, как это, или 0x1A, в текстовый файл является неопределенное поведение. Практически, он будет работать.)

(Когда я должен был решить подобную проблему, я принял политику написания CRC блока во главе записи, при чтении я проигнорировал все, за что был ошибочный CRC.)

Смежные вопросы