Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
ВнизЧтение файлов с изменяющейся структурой Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.035 c