Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.03.06;
Скачать: CL | DM;

Вниз

Чтение файлов с изменяющейся структурой   Найти похожие ветки 

 
SeDOy   (2005-02-16 16:47) [0]

Мне надо анализировать файлы с данными, Но есть трудности.

Структура файла:
type
file1=record
data:array[1.190] of real;
text:string[1..194];
end;

Кол-во таких записей равно 1440.
Проблема в том что в каждом файле границы массивов могут изменяются, 1..195,1..198 и .т.д,
так же менется и длинна текста.
Мне посути не очень важно считыавть текст, мне нужен только массив значений типа real.

Как это сделать?
Так как дельфя не умеет делать динамический рекорд остаётся только
blockread/write

Но тогда я не пойму как из одной записи мне считать только значения real,
ведь запись(например) занимает 950 байт, из них 790байт значения real,
а остальные 160 байт - текст

Может кто сталкивался с такой ситуацией? помогите плиз!


 
Arm79 ©   (2005-02-16 17:16) [1]

Что то непонятно. Почему границы рекорда вообще плавают? интересно и поле text объявлено.

Вы уверены, что правильно привели структуру файла?

Может так правильнее?

type
 TMyRec = record
   data : real;
   text : string[255];
 end;
 TMyRecArray = array [1..190] of TMyRec;
var
 file1 : file of TMyRec;


Так как дельфя не умеет делать динамический рекорд
Поясните, что это значит


 
icWasya ©   (2005-02-16 18:18) [2]

и как тот, кто пишет, предполагает ЭТО читать


 
SeDOy   (2005-02-16 20:27) [3]

Нет, в моём случае правильно вот так

type
TMyRec = record
  data : real[1..190];
  text : string[194];
end;


так как одна запись это массив значений, а следующий
далее за ним  текст.

Так как дельфя не умеет делать динамический рекорд
Я имел ввиду что во время исполнения программы не возможно изменить границы массивов data и text


 
begin...end ©   (2005-02-16 20:31) [4]

> SeDOy   (16.02.05 20:27) [3]

Т.е. формат файла Вы изменить не можете? Нужно только решить проблему с чтением?


 
begin...end ©   (2005-02-16 21:40) [5]

> SeDOy   (16.02.05 16:47)

> Но тогда я не пойму как из одной записи мне считать
> только значения real, ведь запись(например) занимает
> 950 байт, из них 790байт значения real, а остальные
> 160 байт - текст

Ну так и считывайте нужное количество байт из файла с помощью уже упомянутой Вами процедуры BlockRead.

Например, есть файл с записями такого типа:

type
 TMyRecord = packed record
   Data: array [1..190] of Real;
   Text: string [194]
 end


Как будет выглядеть в файле эта запись, если её записывали именно как запись в типизированный файл (file of TMyRecord)? Вначале идут 190 * 8 = 1520 байт поля-массива Data: первые 8 байт - первый элемент, вторые 8 байт - второй элемент, и т.д. Затем сразу же идут 195 байт поля Text. Почему 195, а не 194? Потому что таков формат коротких строк - первый байт у них содержит длину (в Вашем случае длина равна 194, поэтому байт в файле, следующий за массивом Data, будет равен именно 194), а уже следом за ним идут символы. Таким образом, каждая запись будет занимать в файле 1520 + 195 = 1715 байт.

Следующая запись в файле начинается сразу же за предыдущей и имеет точно такой же формат.

Ну и как же прочитать из файла то, что Вам нужно? Начнём с первой записи. Объявляем нетипизированный файл и читаем из него первые 1520 байт в массив:

var
 F: file;
 Arr: array [1..190] of Real;
begin
 AssignFile(F, "{путь к файлу}");
 Reset(F, 1);
 BlockRead(F, Arr, 1520);
 CloseFile(F)
end.


Вот и всё - теперь массив Arr заполнен.

А как прочитать, например, вторую запись? Для этого нужно сместиться в файле на нужную позицию. Если первая запись занимает 1715 байт, то, если считать, что нумерация байтов в файле начинается с нуля, получается, что первая запись занмает байты 0..1715, а вторая запись начинается с 1715-го байта. Используем процедуру Seek и читаем:

var
 F: file;
 Arr: array [1..190] of Real;
begin
 AssignFile(F, "{путь к файлу}");
 Reset(F, 1);
 Seek(F, 1715);
 BlockRead(F, Arr, 1520);
 CloseFile(F)
end.


Теперь в массиве Arr будет содержимое поля Data из второй записи (если, конечно, вторая запись в файле была).

Разумеется, вместо конкретных чисел (1520 и 195) можно использовать функцию SizeOf (SizeOf(MyRecord.Data) и SizeOf(MyRecord.Text)).

Всё вышесказанное относится к случаю, когда в файл были записаны упакованные (packed) записи. В случае неупакованных дело несколько усложняется.

Только объясните, наконец - почему бы всё-таки не читать из файла именно записи, и потом в этих записях использовать только поле Data, а на поле Text просто не обращать внимание?


 
begin...end ©   (2005-02-16 21:43) [6]

> begin...end ©   (16.02.05 21:40) [5]

> получается, что первая запись занмает байты 0..1715, а
> вторая запись начинается с 1715-го байта

Опечатка. Следует читать: "получается, что первая запись занимает байты 0..1714, а вторая запись начинается с 1715-го байта".


 
Slym ©   (2005-02-17 06:37) [7]

Сделай с запасом:
type
TMyRecord = packed record
  DataSize:byte;
  Data: array [1..200] of Real;
  Text: string [255];
end

Все данные поместятся...
DataSize пиши количество данных в штуках
Text заканчивай #0


 
Arm79 ©   (2005-02-17 09:59) [8]

2 Slym ©   (17.02.05 06:37) [7]

Text заканчивай #0
При таком объявлении Text нет нужды в #0. Это же ShortString

2 SeDOy   (16.02.05 20:27) [3]
Границы менять можно. Вам ни о чем не говорят динамические массивы?
это объявления типа array of real без указания границ диапазона. Границы устанавливаются в коде через SetLength.

2 begin...end ©   (16.02.05 21:40) [5]
Насколько я понимаю, если объявить переменную F: file как F: file of TMyRecord, то можно обойтись отлично и без BlockRead. Обычный Read вполне подойдет. И смещения вычислять не нужно.

Согласен, форма организации записей в файл нелогична


 
begin...end ©   (2005-02-17 11:02) [9]

> Arm79 ©   (17.02.05 9:59) [8]

> Насколько я понимаю, если объявить переменную F: file
> как F: file of TMyRecord, то можно обойтись отлично и
> без BlockRead.

Разумеется. Я просто ответил на вопрос автора ветки о том, как считывать запись не целиком, а только отдельные её поля. Хотя для чего это может быть необходимо - не знаю. И об этом я тоже сказал в конце [5].

> Границы менять можно. Вам ни о чем не говорят
> динамические массивы?

Если сделать в записи поле типа динамический массив, то тогда уже обычным типизированным файлом (а следовательно, и процедурой Read) не обойтись.

Вопрос до сих пор неясен. Если в записях переменная длина полей (например, поля Data представляют собой массивы различной длины), то в таких случаях от записей обычно отказываются и пишут в нетипизированный файл по схеме "длина данных - сами данные".


 
Arm79 ©   (2005-02-17 11:13) [10]

2 begin...end ©   (17.02.05 11:02) [9]
Так и я про то же. Мне не понятно, то ли есть уже файлы, которые надо проанализировать, то ли он сам их пишет, а потом анализирует...

Если сам, то формат файлов бредовый. А если не сам, то могу только посочувствовать


 
esu ©   (2005-02-17 12:33) [11]

Если нужно просто узнать какой тип использовать для чтения то получается.
1440*размер одной записи=размер файла
размер одной записи = 195 + x*sizeof(real)

решаем уравнение, получаем x далее по этому x можно использовать тот или иной тип.



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

Текущий архив: 2005.03.06;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.065 c
1-1109055854
leonidus
2005-02-22 10:04
2005.03.06
После задание форме св-ва"поверх всех" не могу вернуть ее обратн


3-1107862956
Mishenka
2005-02-08 14:42
2005.03.06
Как с помощью DBImage просмотреть gif ы из базы?


3-1107433780
Floppy
2005-02-03 15:29
2005.03.06
ODBC, MSAccess, Alias


1-1108381391
BFG9k
2005-02-14 14:43
2005.03.06
Как работает функция pos ?


1-1108753570
Ji
2005-02-18 22:06
2005.03.06
Магнитные бури???