Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];

Вниз

Обрезка файла   Найти похожие ветки 

 
Igor_Z   (2007-01-06 09:34) [0]

Уважаемые мастера.
Скажите, как обрезать нетипизированный файл
от одной границы байт до другой.
Truncate работает не так хорошо, если
запись в середине, и нужно, удалить ее одну, он не справится.
Может есть какой-либо еще метод.
Спасибо.


 
kaZaNoVa ©   (2007-01-06 10:11) [1]

никак .. только копированиее и обрезка


 
ors_archangel ©   (2007-01-06 10:43) [2]

Если часто нужно удалять блоки внутри файла, и размер файла может быть большим, то это приведёт к тому, что нужно будет перезаписывать большие блоки данных, наприер, в 3 Mb файле вырезаем 100 байт из середины - придётся перезаписать со смещением 1.5 Mb - 100 байт. Если файл не большого размера, то нет проблем, но если записей много, то лучше в файле организовать подобие кластерной системы - физически неупорядоченное хранение, в простейшем случае, если все записи имеют одинаковую длину, можно просто хранить двусвязный список, только укзаатели будут в файле, а не как обычно - в памяти, т.к. двусвязанные списки позволяют удалять записи с эффективностью O(1): например нужно из файла, содержащего n записей удалить одну посредине: мы перемещаем последнюю запись на место данной плюс модифицируем указатели на эту запись, чтобы они были актуальны, но предварительно, чтобы не нарушить упорядоченность записей, нужно указатель на удаляемую запись заменить указателем на следующю запись, т.е. что-то подобное:

procedure DeleteRecord(f: THandle; n: integer);
var
 t: TRecord;
begin
{ читаем запись (точнее её часть) }
 FileSeek(f, n*RECORD_SIZE, 0);
 FileRead(f, t, 8);
{ указатель на запись меняем на следующий указатель }
 FileSeek(f, t.prev*RECORD_SIZE + 4, 0);
 FileWrite(f, t.next, 4);
{ на место удаляемой записи записываем последнюю запись из файла }
 FileSeek(f, -RECORD_SIZE, SEEK_END);
 FileRead(f, t, RECORD_SIZE);
 FileSeek(f, -RECORD_SIZE, SEEK_END);
 SetEndOfFile(f); // обрезка файла
 FileSeek(f, n*RECORD_SIZE, 0);
 FileWrite(f, t, RECORD_SIZE);
{ обновляем указатель на перемещённую запись }
 FileSeek(f, t.prev*RECORD_SIZE + 8, 0);
 FileWrite(f, n, 4); // записываем новое местоположение
end;

этот лишь примерный код, тут нужно рассмотреть ещё разные случаи, например, когда удаляемая запись - последняя, когда последняя запись ссылалась на удалённую и т.д. Минус такого хранения в том, что нужно +8 байт на каждую запись, но если тебе не важен порядок хранения, тогда всё намного проще: просто читаешь последню запись, записываешь её на место удаляемой и обрезаешь файл


 
Anatoly Podgoretsky ©   (2007-01-06 11:52) [3]

> Igor_Z  (06.01.2007 09:34:00)  [0]

А ты бы для начала определился, что тебе нужно обрезка или смещение.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.46 MB
Время: 0.041 c
2-1168071121
lo111
2007-01-06 11:12
2007.01.21
ASCII + #


2-1167404791
gsm1
2006-12-29 18:06
2007.01.21
вывод окна.


3-1162552706
salexn
2006-11-03 14:18
2007.01.21
Ошибки фильтрации TClientDataSet


2-1168028135
Влад
2007-01-05 23:15
2007.01.21
Текущее время


6-1156099409
ronyn
2006-08-20 22:43
2007.01.21
Как узнать о коннекте?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский