простой способ разобрать текстовый файл? - PullRequest
0 голосов
/ 06 марта 2011

Я делаю балансировщик нагрузки (очень простой). Он показывает, как долго пользователь простаивал, и нагрузку на систему, чтобы определить, может ли процесс выполняться, и проходит ли он циклически.

Все данные, необходимые для управления процессами, хранятся в текстовом файле. Файл может выглядеть так:

 PID=4390 IDLE=0.000000 BUSY=2.000000 USER=2.000000
 PID=4397 IDLE=3.000000 BUSY=1.500000 USER=4.000000
 PID=4405 IDLE=0.000000 BUSY=2.000000 USER=2.000000
 PID=4412 IDLE=0.000000 BUSY=2.000000 USER=2.000000
 PID=4420 IDLE=3.000000 BUSY=1.500000 USER=4.000000

Это университетское задание, однако разбор текстового файла не должен быть большой его частью, а это значит, что я могу использовать любой способ, который быстрее всего реализовать.

Записи в этом файле будут добавлены и удалены по завершении процессов или добавлены под контроль.

Есть идеи как разобрать это?

Спасибо.

Ответы [ 3 ]

1 голос
/ 06 марта 2011

Что касается простого синтаксического анализа, то что-то вроде этого в цикле:

int pid;
float idle, busy, user;
if(fscanf(inputStream, "PID=%d IDLE=%f BUSY=%f USER=%f", %pid, &idle, &busy, &user)!=4)
{
    /* handle the error */
}

Но, как указал @Blrfl, большая проблема состоит в том, чтобы избежать путаницы, когда ваше приложение читает файл идругие пишут в него.Чтобы решить эту проблему, вы должны использовать замок или что-то подобное;см., например, flock системный вызов.

1 голос
/ 06 марта 2011

Вот код, который будет анализировать ваш файл, а также учитывать тот факт, что ваш файл может быть недоступен (то есть, fopen может произойти сбой), или записывается во время чтения (то есть fscanf)может провалиться).Обратите внимание на бесконечный цикл, который вы, возможно, не захотите использовать (это скорее псевдокод, чем реальный код, который нужно вставить в ваш проект, я не пытался его запускать).Также обратите внимание, что это может быть довольно медленно, учитывая длительность сна: вы можете использовать более продвинутый подход, это скорее своего рода взлом.

int pid;
float idle, busy, user;

FILE* fid;
fpos_t pos;
int pos_init = 0;

while (1)
{
  // try to open the file
  if ((fid = fopen("myfile.txt","rw+")) == NULL)
  {
     sleep(1); // sleep for a little while, and try again
     continue; 
  }

  // reset position in file (if initialized)
  if (pos_init)
     fsetpos (pFile,&pos);

  // read as many line as you can
  while (!feof(fid))
  {
     if (fscanf(fid,"PID=%d IDLE=%f BUSY=%f USER=%f",&pid, &idle, &busy, &user))
     {
        // found a line that does match this pattern: try again later, the file might be currently written
        break;
     }

     // add here your code processing data         

     fgetpos (pFile,&pos); // remember current position
     pos_init = 1; // position has been initialized
  }

  fclose(fid);
}
0 голосов
/ 06 марта 2011

Используйте fscanf в цикле.Вот учебник GNU C по использованию fscanf .

/* fscanf example */
#include <stdio.h>

typedef struct lbCfgData {
    int pid;
    double idle;
    double busy;
    double user;
} lbCfgData_t ;

int main ()
{
    // PID=4390 IDLE=0.000000 BUSY=2.000000 USER=2.000000
    lbCfgData_t cfgData[128];

    FILE *f;

    f = fopen ("myfile.txt","rw+");
    for (   int i = 0; 
            i != 128 // Make sure we don't overflow the array
            && fscanf(f, "PID=%u IDLE=%f BUSY=%f USER=%f", &cfgData[i].pid, 
                &cfgData[i].idle, &cfgData[i].busy, cfgData[i].user ) != EOF; 
            i++
        );

    fclose (f);
    return 0;
}
...