Как правильно работать с файлами

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Ответить
mirk
постоялец
Сообщения: 319
Зарегистрирован: 24.09.2007 10:03:39

Как правильно работать с файлами

Сообщение mirk »

Пишу в файл довольно просто:

Код: Выделить всё

assign(f, '.....');
rewrite(f, 1);
blockwrite(fd, buf^, size);


Но оптимально ли это?
Пишется ли это одним буфером или побайтно?
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Имхо лучше использовать вариант с хэндлами файлов, а не с файловыми переменными. Еще лучше наверно потоки.
mirk
постоялец
Сообщения: 319
Зарегистрирован: 24.09.2007 10:03:39

Сообщение mirk »

zub писал(а):Имхо лучше использовать вариант с хэндлами файлов, а не с файловыми переменными.

Это что? Я думал fd в моем случае и есть хэндл.

zub писал(а):Еще лучше наверно потоки.

TFileStream?
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Это что? Я думал fd в моем случае и есть хэндл.
в вашем случае

Код: Выделить всё

...
var
fd:file;
...

Приводите полный код пжст, телепаторы ломаются часто))
я говорю о

Код: Выделить всё

program Project1;
uses sysutils;
var
   fh:THandle;
   something:integer;
begin
   fh:=FileCreate('test.test');
   FileWrite(fh, something, sizeof(something));
   FileClose(fh);
end.


>>TFileStream?
да
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3071
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

Вообще-то первые два способа доступа к файлу - это, всего лишь, обертки над TFileStream. Так что принципиальной разницы я не вижу.
Как писать буфер, вроде бы, в любом случае определяет файловая система ОС.
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

Снег Север писал(а):Вообще-то первые два способа доступа к файлу - это, всего лишь, обертки над TFileStream.

Нет, сам TFileStream — обёртка над хендлами:

rtl/objpas/classes/streams.inc

Код: Выделить всё

function THandleStream.Write(const Buffer; Count: Longint): Longint;

begin
  Result:=FileWrite (FHandle,Buffer,Count);
  If Result=-1 then Result:=0;
end;

....

constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);

begin
  FFileName:=AFileName;
  If (Mode and fmCreate) > 0 then
    FHandle:=FileCreate(AFileName,Mode,Rights)
  else
    FHAndle:=FileOpen(AFileName,Mode);

  If (THandle(FHandle)=feInvalidHandle) then
    If Mode=fmcreate then
      raise EFCreateError.createfmt(SFCreateError,[AFileName])
    else
      raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
end;
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Вообще-то первые два способа доступа к файлу - это, всего лишь, обертки над TFileStream.
Тогда уж TFileStream обертка над "хэндловыми" файлами, но не наоборот.

Если выбирать из file и thandle - в последнем емнип набор функций побогаче
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

mirk писал(а):Но оптимально ли это?
Пишется ли это одним буфером или побайтно?

Это оптимально. Файл пишется всем блоком сразу, не побайтно.
shyub
постоялец
Сообщения: 112
Зарегистрирован: 25.11.2014 22:15:19

Сообщение shyub »

Если необходимо писать большие объёмы данных, то целесообразно использовать поток:

Код: Выделить всё

var
  Stream: TFileStream;
  BufStr: TWriteBufStream;
  M: array{1..300] of byte;
  ...
begin
  .........
  if SaveDialog1.Execute then begin
    try
      Stream:=TFileStream.Create(SaveDialog1.FileName, fmCreate or fmOpenWrite);
      BufStr:=TWriteBufStream.Create(Stream);
      BufStr.Write(M, 300);
      Result:=false;
      finally
        BufStr.Free;
        Stream.Free;
      end;
   end;
end;

Размер записываемого массива указан 300 байт для примера. Реально при таком размере преимуществ потока не увидите.

Добавлено спустя 6 минут 40 секунд:
Кажется я не правильно объявил массив. Надо было от 0 до 299 (не уверен, но у себя объявляю от 0).
stanilar
постоялец
Сообщения: 289
Зарегистрирован: 09.03.2010 18:09:02

Сообщение stanilar »

mirk писал(а):Но оптимально ли это?

Это костыль для поддержки кода из далеких девяностых. И, извините за любопытство, зачем Вам знать о том, насколько это оптимально?

zub писал(а):Если выбирать из file и thandle - в последнем набор функций побогаче

В последнем случае имеется весь набор Windows API, не знаю как в линухе.

З.Ы. Думаю что выбор лучше остановить на том, что удобнее в конкретном случае.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

Во первых это не костыль, а во вторых винапи тут не причем
SSerge
энтузиаст
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Сообщение SSerge »

zub писал(а):Если выбирать из file и thandle - в последнем емнип набор функций побогаче


imho, не из соображений богатства функций стоит выбирать между этими двумя, а из тех соображений, что file - буферизованный интерфейс, хотите этого или нет, а handle - прямой интерфейс операционной системы, а дальше быстродействие зависит от того, поддерживает операционная система или нет буферизацию ввода/вывода для конкретного диска. Если вдруг ей позарез надо будет флушить операции записи после записи или чтения каждого байта - то получится катастрофическое падение производительности. В DOS это было очень наглядным.
Mikhail
энтузиаст
Сообщения: 565
Зарегистрирован: 24.10.2013 16:06:47

Сообщение Mikhail »

mirk писал(а):Пишу в файл довольно просто:

Код: Выделить всё

assign(f, '.....');
rewrite(f, 1);
blockwrite(fd, buf^, size);


Но оптимально ли это?
Пишется ли это одним буфером или побайтно?


В Windows и Linux будет буферизоваться ОС. Но это, все равно, не очень хорошо, т.к. буфер будет "на стороне ядра" и доступ к нему потребует переключения контекста. Лучше сделать буфер на стороне приложения, если данных много.

Никого не слушайте, дескрипторы тут не при чем. Если требуется тонкий контроль IO, то можно использовать THandleStream или FileRead(Write).
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Паскаль буферизует только текстовые файлы (тип textfile). Типизированные (file of foo) и нетипизированные (просто file) файлы не буферизуются и представляют собой такую же тоненькую обертку над системными вызовами, что и остальные упомянутые способы. Разница только в синтаксисе.
Ответить