![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Чтение файлов с изменяющейся структурой [D6, Win2k, WinXP]
SeDOy © (2005-02-16 16:47:00)Мне надо анализировать файлы с данными, Но есть трудности.
Структура файла:
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 байт - текст
Может кто сталкивался с такой ситуацией? помогите плиз!
esu (2005-02-17 12:33:00) [1]Если нужно просто узнать какой тип использовать для чтения то получается.
1440*размер одной записи=размер файла
размер одной записи = 195 + x*sizeof(real)
решаем уравнение, получаем x далее по этому x можно использовать тот или иной тип.
Arm79 (2005-02-17 11:13:00) [2]2 begin...end © (17.02.05 11:02) [9]
Так и я про то же. Мне не понятно, то ли есть уже файлы, которые надо проанализировать, то ли он сам их пишет, а потом анализирует...
Если сам, то формат файлов бредовый. А если не сам, то могу только посочувствовать
begin...end (2005-02-17 11:02:00) [3]> Arm79 © (17.02.05 9:59) [8]
> Насколько я понимаю, если объявить переменную F: file
> как F: file of TMyRecord, то можно обойтись отлично и
> без BlockRead.
Разумеется. Я просто ответил на вопрос автора ветки о том, как считывать запись не целиком, а только отдельные её поля. Хотя для чего это может быть необходимо - не знаю. И об этом я тоже сказал в конце [5].
> Границы менять можно. Вам ни о чем не говорят
> динамические массивы?
Если сделать в записи поле типа динамический массив, то тогда уже обычным типизированным файлом (а следовательно, и процедурой Read) не обойтись.
Вопрос до сих пор неясен. Если в записях переменная длина полей (например, поля Data представляют собой массивы различной длины), то в таких случаях от записей обычно отказываются и пишут в нетипизированный файл по схеме "длина данных - сами данные".
Arm79 (2005-02-17 09:59:00) [4]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 вполне подойдет. И смещения вычислять не нужно.
Согласен, форма организации записей в файл нелогична
Slym (2005-02-17 06:37:00) [5]Сделай с запасом:
type
TMyRecord = packed record
DataSize:byte;
Data: array [1..200] of Real;
Text: string [255];
end
Все данные поместятся...
DataSize пиши количество данных в штуках
Text заканчивай #0
begin...end (2005-02-16 21:43:00) [6]> begin...end © (16.02.05 21:40) [5]
> получается, что первая запись занмает байты 0..1715, а
> вторая запись начинается с 1715-го байта
Опечатка. Следует читать: "получается, что первая запись занимает байты 0..171 4, а вторая запись начинается с 1715-го байта".
begin...end (2005-02-16 21:40:00) [7]> SeDOy (16.02.05 16:47)
> Но тогда я не пойму как из одной записи мне считать
> только значения real, ведь запись(например) занимает
> 950 байт, из них 790байт значения real, а остальные
> 160 байт - текст
Ну так и считывайте нужное количество байт из файла с помощью уже упомянутой Вами процедуры BlockRead.
Например, есть файл с записями такого типа:
type
TMyRecord = packedrecord
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 20:31:00) [8]> SeDOy (16.02.05 20:27) [3]
Т.е. формат файла Вы изменить не можете? Нужно только решить проблему с чтением?
SeDOy (2005-02-16 20:27:00) [9]Нет, в моём случае правильно вот так
type
TMyRec = record
data : real[1..190];
text : string[194];
end;
так как одна запись это массив значений, а следующий
далее за ним текст.
Так как дельфя не умеет делать динамический рекорд
Я имел ввиду что во время исполнения программы не возможно изменить границы массивов data и text
icWasya (2005-02-16 18:18:00) [10]и как тот, кто пишет, предполагает ЭТО читать
Arm79 (2005-02-16 17:16:00) [11]Что то непонятно. Почему границы рекорда вообще плавают? интересно и поле text объявлено.
Вы уверены, что правильно привели структуру файла?
Может так правильнее?
type
TMyRec = record
data : real;
text : string[255];
end;
TMyRecArray = array [1..190] of TMyRec;
var
file1 : file of TMyRec;
Так как дельфя не умеет делать динамический рекорд
Поясните, что это значит