link9230 link9231 link9232 link9233 link9234 link9235 link9236 link9237 link9238 link9239 link9240 link9241 link9242 link9243 link9244 link9245 link9246 link9247 link9248 link9249 link9250 link9251 link9252 link9253 link9254 link9255 link9256 link9257 link9258 link9259 link9260 link9261 link9262 link9263 link9264 link9265 link9266 link9267 link9268 link9269 link9270 link9271 link9272 link9273 link9274 link9275 link9276 link9277 link9278 link9279 link9280 link9281 link9282 link9283 link9284 link9285 link9286 link9287 link9288 link9289 link9290 link9291 link9292 link9293 link9294 link9295 link9296 link9297 link9298 link9299 link9300 link9301 link9302 link9303 link9304 link9305 link9306 link9307 link9308 link9309 link9310 link9311 link9312 link9313 link9314 link9315 link9316 link9317 link9318 link9319 link9320 link9321 link9322 link9323 link9324 link9325 link9326 link9327 link9328 link9329 link9330 link9331 link9332 link9333 link9334 link9335 link9336 link9337 link9338 link9339 link9340 link9341 link9342 link9343 link9344 link9345 link9346 link9347 link9348 link9349 link9350 link9351 link9352 link9353 link9354 link9355 link9356 link9357 link9358 link9359 link9360 link9361 link9362 link9363 link9364 link9365 link9366 link9367 link9368 link9369 link9370 link9371

Форум — Ответы     (  К темам )
 ?  NewBie: Обработка текстового файла (17-05-2003 07:20:43)
Здравствуйте,
такая задача, мне необходимо с текстового файла считывать порции по 428 байтов, находить поля "ID: " и считывать то что после него, следующие 3 байта.Предложите какой-нибудь эффективный способ плиз.
 Павел (18-05-2003 14:00:55)
Самый эффективный — держать данные не в текстовом файле, а в таблице
(например .db файл), и работать как с таблицей, пользуясь компонентами
Table или Query — у них много соответствующих свойств и методов

----

Если все-же о текстовом файле

void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
struct SSS{
char a[428];
}sss;

AnsiString snum;

// сначала запишем что либо в файл
int ih = FileCreate("c:\\ccc.txt");
for(int i=0; i<10; i++){ // пишем какие-то 10 записей с ID: от 001 до 009
snum.printf("ID:%03d",i);
ListBox2->Items->Add(snum); // проверяем чего пишем
strcpy(sss.a, snum.c_str());
FileWrite(ih, (char*)&sss, 428);
}
FileClose(ih);

//---
ih = FileOpen("c:\\ccc.txt",fmOpenRead);
for(int i=0; i<10; i++){
FileRead(ih, (char*)&sss, 428); // считываем следующие 428 байт
AnsiString s = sss.a;
// находим в них "ID:" и считываем 3 байта после них
AnsiString sn = s.SubString(s.Pos("ID:")+3,3);
ListBox1->Items->Add(sn); // проверяем чего считали из файла
}
FileClose(ih);
}
//-------------------------------------

Если нужно считывать не весь файл от начала до конца,
а какую-то конкретную запись от начала файла,
то воспользуйтесь функцией FileSeek():

// считать 3-и запись те 3-и 428 байт (от начала файла это сдвиг на 2*428)

ih = FileOpen("c:\\ccc.txt",fmOpenRead);
FileSeek(ih,2*428,0); // сдвигаемся от начала на 2*428 = 3 запись
FileRead(ih, (char*)&sss, 428);
AnsiString s = sss.a;
AnsiString sn = s.SubString(s.Pos("ID:")+3,3);
ShowMessage(sn);
FileClose(ih);
 SKh (21-05-2003 08:53:35)
Все понял!Отлично спасибо! только объясните еще одно по подробней.
меня интересует значение "+3,3" в данной строке. Я так понял, что это считывание следующих 3-х байтов после слова "ID:"

s.SubString(s.Pos("ID:")+3,3);

если мне надо теперь считать 15 байтов, то я пишу 15,15?
 Павел (21-05-2003 10:12:07)
Нет, неправильно.

Функция SubString() возвращает подстроку из строки AnsiString.


AnsiString __fastcall SubString(int index, int count) const;

Описание.

SubString вернет новую строку типа AnsiString, являющуюся подстрокой
в данной строке. Подстрока будет содержать count символов, начиная с позиции
index в строке AnsiString.
(те из строки будет вырезано count символов, начиная с позиции index)
index начинается с 1

Если надо считать 15 байтов, то и пишите: s.SubString(s.Pos("ID:")+3,15);

Чтобы было понятней, разберем s.SubString(s.Pos("ID:")+3,15); по частям:

int Pos(AnsiString) — найти подстроку в строке, вернуть позицию начала
подстроки, если строка найдена, иначе 0
AnsiString SubString(index, count) — вернуть подстроку начиная с позиции
index длиной count байт

int n = s.Pos("ID:");
n = n + 3;
AnsiString sn = s.SubString(n, 15);
------------------------------------------------------

Или, пример
Есть строка:


AnsiString s = "This data is ID:12345 and NameIs=Pasha and City:Moscow-city ";

int index = s.Pos("ID:"); // находим подстроку "ID:", получаем в index
номер начала этой подстроки
index = index + 3; // сдвигаемся на 3 байта вправо (на номер)

AnsiString sn = s.SubString(index,5); // вырезаем с указанного index места
подстроку размером 5 байт (номер)
ShowMessage(sn); // "12345"

//----- Теперь также получим значение NameIs
index = s.Pos("NameIs");
index = index + 7;
sn = s.SubString(index,10);
ShowMessage(sn); // "Pasha "

//----- Теперь также получим значение City
index = s.Pos("City");
index = index + 5;
sn = s.SubString(index,15);
ShowMessage(sn); // "Moscow-city "

---


 Павел (21-05-2003 12:42:11)
Кроме того, у вас текстовый файл может состоять и из строк разной длины
Рассмотрим, например, такой пример
Есть текстовый файл subscribe.txt
типа mail*дата время со строками разной длины

mosc@valuehost.ru*2002-12-22 19:41:36
klassiks@mtu-net.ru*2002-12-22 19:42:53
support@rxlib.ru*2002-12-22 19:43:13
moscowin@valuehost.ru*2002-12-22 19:44:27
shop@rol.ru*2002-12-23 16:02:33
gazpr1@sinn.ru*2002-12-24 11:02:25
...
Email-адрес отделен от даты-времени символом *
Нужно выбрать все email-адреса и поместить их в ListBox1
и в другой текстовый файл mail.txt

Тогда чтение строк из файла можем осуществлять через функции C

#include <stdio.h>

char msg[100];
ListBox1->Items->Clear();
AnsiString sDir = GetCurrentDir();
AnsiString sFile = sDir + "\\"+"subscribe.txt";
FILE *fp = fopen(sFile.c_str(), "rt");

while(!feof(fp)){
fgets(msg, 80, fp); // считать следующую строку из файла
AnsiString s = AnsiString(msg);
s = s.Trim(); // удалить начальные/конечные пробелы в строке если есть
AnsiString sMail = s.SubString(1,s.Pos("*")-1); // вырезать адрес в sMail
ListBox1->Items->Add(sMail);
}

fclose(fp);
ListBox1->Items->SaveToFile(sDir + "\\"+"mail.txt");