Функция FileSize в типизированных файлах

Вопросы программирования на Free Pascal, использования компилятора и утилит.

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

Ответить
Александр Яшин
новенький
Сообщения: 67
Зарегистрирован: 21.11.2009 08:31:01

Функция FileSize в типизированных файлах

Сообщение Александр Яшин »

Во всех книгах написано, что функция FileSize для типизированных файлов возвращает количество записей в файле. У меня, почему-то возвращает количество байтов в файле. Вот код:

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

program create_files;
{$mode objfpc}{$H+} {$APPTYPE CONSOLE}
uses CRT, FileUtil, SysUtils;
type
    manager=record
    name:string[18];
    comp: integer;
 end;
var
  company:manager;
  fmanager: File of manager; // Файловая переменная
  k, n:integer;
begin
  AssignFile(fmanager,'File_manager.dat');
  if not FileExists('File_manager.dat') then
    Rewrite(fmanager)
  else
    Reset(fmanager);
  Seek(fmanager, FileSize('File_manager.dat'));
  writeln(UTF8ToConsole('Введите количество менеджеров компании'));
  readln(n);
  with company do
  begin
    for k:=1 to n do
    begin
      writeln(UTF8ToConsole('Введите фамилию'));
      readln(name);
      writeln(UTF8ToConsole('Введите количество реализованных им компьютеров'));
      readln(comp);
      Write(fmanager, company); // запись в файл
    end;
  end;
  writeln(UTF8ToConsole('Информация на диск записана'));
  CloseFile(fmanager);
  writeln(UTF8ToConsole('Нажмите любую клавишу'));
  readkey;
end. 


Так я создаю файл. Для примера создаю предыдущей программой файл с двумя записями.
Теперь пытаюсь с ним работать.
Total Commander показывает размер файла 48 байт и функция FileSize тоже возвращает 48, хотя должна была возвратить число 2. Фрагмент кода:

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

program manager_computer;
{$mode objfpc}{$H+} {$APPTYPE CONSOLE}
uses crt, FileUtil, SysUtils;
type
    manager=record
    name:string[18];
    comp: integer;
 end;
var
  company:manager;
  fmanager: File of manager; // Файловая переменная
  sum, cost, prem, k, n: integer;
  sumc, sumv, sump, sum1: integer;
begin
  if not FileExists('File_manager.dat') then
  begin
    writeln(UTF8ToConsole('Файлы не существуют'));
    writeln(UTF8ToConsole('Сначала создайте их'));
    writeln(UTF8ToConsole('Нажмите любую клавишу'));
    readkey;
    exit;
  end;
  AssignFile(fmanager,'File_manager.dat');
  Reset(fmanager);
  n:= FileSize('File_manager.dat');
  writeln('FileSize= ', n);
  readkey; 


Что здесь я неправильно делаю?
Подскажите, пожалуйста, а то скоро сессия.
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Существуют две версии данной функции:
  • 1 function FileSize(const Filename: string): int64;
  • 2 function FileSize(var f: File): int64;
Вы используете первую функцию, которая возвращает полный объём файла. Для того чтобы получить размер именно типизированного файла вам необходимо вызвать вторую функцию.
Чтобы её вызвать необходимо передать ей параметр соответствующего типа:

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

...
  AssignFile(fmanager,'File_manager.dat');
  Reset(fmanager);
  n:= FileSize(fmanager);
...

и ещё я бы вам рекомендовал элемент записи файла объявлять как packed record :wink:
Александр Яшин
новенький
Сообщения: 67
Зарегистрирован: 21.11.2009 08:31:01

Сообщение Александр Яшин »

Я так вначале и делал.
Выдается ошибка:

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

manager.lpr(29,24) Error: Incompatible type for arg no. 1: Got "File Of manager", expected "AnsiString"


Кроме того, мои многочисленные эксперименты по созданию файлов первой программой показывают, что в первой программе вызывает сомнение и функция

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

 Seek(fmanager, FileSize('File_manager.dat'));

Вызов этой функции в таком виде

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

 Seek(fmanager, FileSize(fmanager));

также дает ошибку компиляции с тем же сообщением

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

create_files.lpr(22,35) Error: Incompatible type for arg no. 1: Got "File Of manager", expected "AnsiString"
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Укажите конкретно тот модуль в котором описана данная функция.

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

System.FileSize()
Александр Яшин
новенький
Сообщения: 67
Зарегистрирован: 21.11.2009 08:31:01

Сообщение Александр Яшин »

Спасибо большое!
Получилось. А что, нет ли каких-то умолчательных настроек, чтобы не писать
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

Тут ситуация следующая. Существуют 2 функции с одинаковыми названиями. Одна в модуле System, а вторая в FileUtil.
Т.к. модуль FileUtil подключен позже чем System (который подключается по умолчанию ко всем модулям первым) то компилятор считает, что данная функция имеет параметр типа const String и ругается.
Если вы не пользуетесь модулем FileUtil то просто удалите его из секции uses :wink:
Александр Яшин
новенький
Сообщения: 67
Зарегистрирован: 21.11.2009 08:31:01

Сообщение Александр Яшин »

Спасибо!
Модуль FileUtil я применяю (функцию UTF8ToConsole), так что придется через точку.
Аватара пользователя
VirtUX
энтузиаст
Сообщения: 880
Зарегистрирован: 05.02.2008 09:52:19
Откуда: Крым, Алушта

Сообщение VirtUX »

Интересно: как правильно подключить в консольном приложении модуль FileUtil, чтоб не было ошибок?
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

VirtUX
Нужно подключить пакет LCL и получить кучу "мёртвого" кода.
Ответить