paulo1205
(usa Ubuntu)
Enviado em 09/09/2014 - 13:04h
willdoidao escreveu:
Pessoal,
Como faço para caprturar dados sepadorados de uma linha de arquivo, tipo se der um cat /proc/stat obtenho em uma das linhas o seguinte retorno:
cpu0 96804 9119 387122 6739554 62390 456399 64543 0 0 0
Fiz um script bem ralé só para testar, pretendo melhorar bem o código e otimizar mas primeiro preciso fazer funcionar.
Já consegui fazer o levantamento da quantidade, setar a linha que contém
cpu0, mas não sei como dividir esses números na frente dela em variavés.
Como você está usando C++, pode usar
std::getline () (dentro de <string>) para ler as linhas, e depois colocar essa linha dentro de um
std::istringstring , para enfim separar os campos através de usos sucessivos de
std::istream::operator>> () (uso semelhante a quando você lê de
std::cin , por exemplo). Pode também aplicar sobre esse
std::istringstream um
loop com
std::getline (), usando espaços (e não '\n', que é o
default ) como separador. Pode, ainda, descer um pouco mais o nível, e usar
std::string::find (),
std::string::substr () e outras funções relacionadas.
Segue um exemplo usando C++11.
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <map>
#include <vector>
using namespace std;
// Largura das colunas na hora de imprimir os dados lidos.
const unsigned col_width=11u;
int main(){
// Vetor com os titulos das colunas. Os nomes das colunas são
// passados para um construtor que utiliza a nova sintaxe do
// C++11, que aceita uma lista de elementos.
vector<string> col_names{
"CPU", "user", "nice", "system", "idle", "iowait",
"irq", "softirq", "stolen", "guest", "guest_nice"
};
// cpu_data faz o mapeamento entre o nome de uma CPU (string) e
// uma lista de contadores (vetor de inteiros sem sinal). Eu
// usei um vetor de valores sem nomes predefinidos porque cada
// versão de kernel pode ter mais ou menos campos do que outras
// versões (sendo que as primeiras quatro ou cinco colunas pa-
// recem ter "sempre" existido). Mas como este programa monta
// uma tabela, eu acabei usando o vetor col_names, definido acima,
// com os nomes de colunas que vi numa manpage.
map<string, vector<unsigned long long>> cpu_data;
// Uma variável inteira sem sinal, que será usada no loop de
// leitura dos sucessivos contadores associados a cada CPU.
unsigned long long counter;
// Um buffer para armazenar cada linha lida.
string line;
// Depois de ler cada linha, eu uso um "input string stream"
// (istringstream, definido em <sstream>) para separar as colunas.
istringstream line_parser;
// Tente descobri qual informação a variável abaixo armazena. ;)
string cpu_name;
// Declara um stream de entrada para ler do arquivo, e já define
// de que arquivo será feita a leitura.
ifstream proc_stat("/proc/stat");
// Lê uma linha do arquivo de entrada. Se a leitura for bem sucedida,
// entra no corpo do while.
while(getline(proc_stat, line)){
// Limpa do objeto separador eventuais sinalizações de erro e/ou
// fim de dados, que podem ter permanecido da iteração anterior do
// loop. Em seguida, alimenta o separador com a linha que acabou
// de ser lida, para que possamos separar suas partes.
line_parser.clear();
line_parser.str(line);
// A primeira coluna da linha é o nome da entidade cujos contadores
// estarão nas colunas seguintes. Como só temos interesse nos con-
// tadores de CPUs, só se entra no corpo do if se essa primeira co-
// luna lida tiver realmente os três primeiros caracteres (i.e. a
// substring começando na posição 0 e com 3 caracteres de compri-
// mento) iguais ao texto "cpu".
if((line_parser >> cpu_name) && cpu_name.substr(0, 3)=="cpu"){
// Existem dois tipo de linha com informações de CPU: as que são
// relativas a cada core, que aparecem com a string "cpu" seguida
// de um número, e a do total consolidado, que aparece apenas como
// "cpu", sem sufixo. Para deixar mais claro, este programa troca
// o rótulo da linha consolidada pela string "TOTAL", usando as
// letras maiúsculas para dar ainda mais destaque à diferença.
if(cpu_name=="cpu")
cpu_name="TOTAL";
// Loop de leitura dos contadores. Cada contador é lido do sepa-
// rador de colunas para a variável counter. Se a leitura for bem
// sucedida, esse valor é colocado ao final do vetor de contadores
// associados à CPU indicada por cpu_name.
while(line_parser >> counter)
cpu_data[cpu_name].push_back(counter);
}
}
// Fecha o arquivo de onde os dados foram lidos.
proc_stat.close();
// Imprime os dados lidos, começando com os títulos das colunas (lem-
// brando que setw() é um manipulador que informa a largura usada para
// o próximo dado a ser impresso)...
for(auto &col : col_names) // itera sobre os nomes das colunas.
cout << setw(col_width) << col;
cout << '\n';
// ... e terminando com a impressão dos dados em si.
for(auto &cpu_info : cpu_data){ // itera sobre os registros do mapa.
// Primeiro imprime o nome da CPU (primeiro campo do registro, que
// é usado no momento da leitura como chave de indexação do mapa)...
cout << setw(col_width) << cpu_info.first;
// ... e depois o valor de cada contador do vetor de contadores (o
// vetor é o segundo campo do registro do mapa).
for(auto &col : cpu_info.second)
cout << setw(col_width) << col;
// Fim dos dados desta CPU: pula a linha.
cout << '\n';
}
}