JavaScript - Aula08

15
ELFS, 2003 183 8. Tratamento de Arquivos w Algumas vezes, uma aplicação precisa ler ou gravar dados em arquivos. Por exemplo: um contador de página da web deve ter acesso a um arquivo onde esteja armazenado o número de visitas ao site, um livro de visitas pode gravar informações num arquivo de texto, um gerador de estatísticas de um site pode armazenar em arquivo o IP, a data e a hora que o usuário solicitou aquela URL. w Para ser manipulado, um arquivo precisa estar aberto. Para isso, devemos utilizar a função int fopen(string nome, string modo), onde nome é um string contendo o nome do arquivo, e modo é um dos modos de abertura especificados na tabela a seguir. Significado Modo Abre o arquivo com permissão apenas para leitura. O arquivo deve existir. r Abre o arquivo com permissão para leitura e escrita. O arquivo deve existir. r+ Abre o arquivo com permissão apenas para escrita. Se o arquivo existir, todo o seu conteúdo atual será apagado. Se não existir, o PHP tenta criá-lo. w Abre o arquivo com permissão para escrita e leitura. Se o arquivo existir, todo o seu conteúdo atual será apagado. Se não existir, o PHP tenta criá-lo. w+ Abre o arquivo com permissão apenas para escrita. Se o arquivo existir, seu conteúdo será mantido. Se o arquivo não existir, o PHP tenta criá-lo. a Abre o arquivo com permissão para escrita e leitura. Se o arquivo existir, seu conteúdo será mantido. Se o arquivo não existir, o PHP tenta criá-lo. a+

description

JavaScript - Aula03

Transcript of JavaScript - Aula08

Page 1: JavaScript - Aula08

ELFS, 2003 183

8. Tratamento de Arquivos

w Algumas vezes, uma aplicação precisa ler ou gravar dados em arquivos. Por exemplo: um contador de página da web deve ter acesso a um arquivo onde esteja armazenado o número de visitas ao site, um livro de visitas pode gravar informações num arquivo de texto, um gerador de estatísticas de um site pode armazenar em arquivo o IP, a data e a hora que o usuário solicitou aquela URL.

w Para ser manipulado, um arquivo precisa estar aberto. Para isso, devemos utilizar a função int fopen(string nome, string modo), onde nome é um string contendo o nome do arquivo, e modo é um dos modos de abertura especificados na tabela a seguir.

SignificadoModo

Abre o arquivo com permissão apenas para leitura. O arquivo deve existir.r

Abre o arquivo com permissão para leitura e escrita. O arquivo deve existir.r+

Abre o arquivo com permissão apenas para escrita. Se o arquivo existir, todo o seu conteúdo atual será apagado. Se não existir, o PHP tenta criá-lo.

w

Abre o arquivo com permissão para escrita e leitura. Se o arquivo existir, todo o seu conteúdo atual será apagado. Se não existir, o PHP tenta criá-lo.

w+

Abre o arquivo com permissão apenas para escrita. Se o arquivo existir, seu conteúdo será mantido. Se o arquivo não existir, o PHP tenta criá-lo.

a

Abre o arquivo com permissão para escrita e leitura. Se o arquivo existir, seu conteúdo será mantido. Se o arquivo não existir, o PHP tenta criá-lo.

a+

Page 2: JavaScript - Aula08

ELFS, 2003 184

Tratamento de Arquivos

w A função fopen() retorna um identificador inteiro se a abertura do arquivo for bem sucedida ou 0, caso contrário.

w Para ler informações de um arquivo deve ser usada a função:string fread(int id, int tamanho), onde id corresponde ao identificador retornado pela função fopen e tamanho indica o número de caracteres a ser lido do arquivo. É possível especificar como tamanho o valor retornado pelafunção filesize(nome_arquivo) para indicar que se deseja ler todo o conteúdo do arquivo. Considere, por exemplo, a página e o arquivo a seguir:

<?php// Nome do arquivo$arq = "contador.txt";// Verificar se o arquivo existeif (file_exists($arq)){$id = fopen($arq, "r");$conteudo = fread($id, filesize($arq));echo $conteudo;

}elseecho "<h1>Arquivo $arq não existe!</h1>";

?>

aula08_01.php

Contém o número de vezes que o site foi visitado:000123

Experimente, em seguida, trocar filesize($arq) pelo valor 15. O que acontece?

Page 3: JavaScript - Aula08

ELFS, 2003 185

Tratamento de Arquivos

w Em sistemas operacionais que diferenciam entre arquivos binários e arquivos de texto (por exemplo, Windows), arquivos binários têm que ser abertos comum 'b' incluído no segundo parâmetro na função fopen(). Exemplo:

w Outra forma de ler todo o conteúdo de um arquivo para um string é usar a função string file_get_contents(string nome-arquivo). Esta função pode ser usada tanto para arquivos de texto como para arquivos binários.

w Para gravar informações em um arquivo devemos usar a função:int fwrite(int id, string valor), onde id corresponde ao identificador do arquivo(retornado pela função fopen) e valor corresponde à informação a ser armazenada no arquivo.

<?php$arq = "c:\\apache\\htdocs\\DAIaula08\\monalisa.jpg";$id = fopen($arq, "rb");if ($id == 0)echo("<h1>Arquivo $arq não pôde ser aberto!</h1>");

else{ $conteudo = fread($id, filesize($arq));

// Algum tratamento do conteúdo do arquivo...

fclose($id);}

?>

O nome do arquivo também pode ser escrito usando barras "normais", ou seja: $arq = "c:/apache/htdocs/DAIaula08/monalisa.jpg". Note a função fclose() para fechar um arquivo aberto. Uma vez fechado, o arquivo pode ser aberto novamente no mesmo modo ou em um outro modo.

aula08_02.php

Page 4: JavaScript - Aula08

ELFS, 2003 186

Tratamento de Arquivos

w Considere, por exemplo, que desejamos atualizar o arquivo contador.txt a cada acesso.

<?php$arq = "contador.txt";if (file_exists($arq)){// Ler a informação atual$id = fopen($arq, "r");$conteudo = fread($id, filesize($arq));

// Encontrar o numero de acessos$pos = strpos($conteudo, ":");$inicio = substr($conteudo, 0, $pos+1);$numero = trim(substr($conteudo, $pos+1, 10));fclose($id);

// Gravar a informação atualizada$id = fopen($arq, "w");$numero++;$visitas = sprintf("%06d", $numero);fwrite($id, $inicio . $visitas);fclose($id);echo("<h2>Site visitado $visitas vezes.</h2>");

}elseecho("<h2>Arquivo $arq não existe!</h2>");

?>

Note que o arquivo foi aberto inicialmente com permissão apenas de leitura (para recuperar a informação) e depois foi aberto com permissão apenas de escrita(para gravar a informação atualizada). Com isto, o arquivo teve que ser fechado para poder ser aberto novamente em outro modo. Para evitar isto, o arquivo poderia ser aberto no modo "r+" ? Sim, mas seria necessário um rewind($id)antes da chamada a fwrite().E no modo "w+" ?

aula08_03.php

aula08_03a.php

Page 5: JavaScript - Aula08

ELFS, 2003 187

Tratamento de Arquivos

w Um outro exemplo: download de arquivos.<?php

function transfere($arq) {$status = FALSE;$nome = basename($arq);

if (!is_file($arq) or connection_status() != 0) return(FALSE);

header("Content-type: application/octet-stream");header("Content-Disposition: attachment; filename=".$nome);header("Content-length: ".(string)(filesize($arq)));header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");header("Cache-Control: no-cache, must-revalidate");header("Pragma: no-cache");

if ($file = fopen($arq,"rb")) {while (!feof($file) and (connection_status() == 0)) {print(fread($file, 8*1024)); flush();

}$status = (connection_status() == 0);fclose($file);

}

aula08_04.php

Se o valor attachment for substituído por inline, arquivos de conteúdos conhecidos serão abertos diretamente.

Note que o download será feito em pacotes de 8 KB. A função flush() força que o "buffer" do sistema seja esvaziado.

Page 6: JavaScript - Aula08

ELFS, 2003 188

Tratamento de Arquivos

w Considere o seguinte arquivo (notas.txt) contendo nomese notas de alunos. O script a seguir exibe as notas dosalunos em uma tabela.

return($status);}

if (!transfere($arq)){die ("<h2>Download de $arq falhou.</h2>");

}

?>

Maria da Silva#8.7João Pereira#7.6Pedro Alvares#5.0José Ribamar#9.5Ana Ferreira#8.0

<?php

$nome_arq = basename($arq);

echo('<table border="1"><thead style="background-color:yellow">'.'<tr><th>Nome</th><th>Nota</th></tr></thead>'.'<tbody align="center">');

if ($file = fopen($arq,"r")) {while (!feof($file))

aula08_05.php

Page 7: JavaScript - Aula08

ELFS, 2003 189

Tratamento de Arquivos

w A linguagem PHP não impõe estrutura alguma aos arquivos: do ponto de vista físico, um arquivo é simplesmente uma sequência (ou fluxo) de bytes. Mas, do ponto de vista lógico, costuma-se imaginar que os dados armazenados em arquivos são organizados em registros. Em um sistema de folha de pagamento, por exemplo, cada registro pode corresponder a um empregado e conter os seguintes dados:n Número de matrículan Nome do empregadon Data de início na empresan Departamento onde trabalha

{$linha = fgets($file,30);$pos = strpos($linha, "#");$aluno = substr($linha, 0, $pos);$nota = substr($linha, $pos+1, 10);echo("<tr><td>$aluno</td><td>$nota</td></tr>");

}

fclose($file);echo("</tbody></table>");

}elseecho("<h2>Arquivo $nome_arq não localizado!</h2>");

?>

A função fgets(arq, n)lê uma linha do arquivo arq, com no máximo ncaracteres.A função strpos(s, c)retorna a posição da primeira ocorrência do string c no string s.A função substr(s, i, t)retorna o substring de sque começa na posição i e tem (no máximo) tcaracteres.

Cada um dos dados que compõem um registro denomina-se campo. Número de matrícula, por exemplo, constitui um campo do registro referente a um empregado.

Page 8: JavaScript - Aula08

ELFS, 2003 190

Tratamento de Arquivos

w Podemos, portanto, imaginar um arquivo de empregados como:

w Em geral, a recuperação dos dados de um arquivo é feita registro a registro. Para facilitar a recuperação, pelo menos um campo deve, univocamente, identificar o registro (chave de registro). No exemplo acima, o campo Número de matrícula pode ser a chave de registro. Os demais campos não podem ser escolhidos como chave de registro, pois podem conter dados iguais (dois empregados podem ter o mesmo nome, ou ter ingressado no mesmo dia na empresa, ou pertencerem ao mesmo departamento).

w Os registros em um arquivo podem ser organizados de várias formas. Na organização mais comum, os registros são organizados em ordem (crescente ou decrescente) de seus campos-chave. Neste caso, o arquivo é conhecido como arquivo sequencial.

Distribuição11/09/1998Lucas1508

Planejamento05/12/2000Cláudio1495

Administração28/11/1999Bruno1432

Planejamento31/05/2002Filipe1380

Financeiro03/01/1994Henrique1367

Recursos Humanos12/03/1985Pedro1245

Um registro

Um campo

Um arquivo

Page 9: JavaScript - Aula08

ELFS, 2003 191

Tratamento de Arquivos

w Em um arquivo sequencial, a recuperação de um registro específico é feita procurando-se por sua chave a partir do primeiro até o último registro do arquivo, passando necessariamente por todos os registros intermediários atéque a chave seja encontrada. Caso o valor da chave não esteja presente no arquivo, a procura sequencial irá alcançar o fim do arquivo sem que algum registro seja recuperado.

w Outra forma de organização dos registros é a de arquivos de acesso aleatório. Nesta forma de organização é possível acessar um registro específico, sem pesquisar quaisquer dos demais registros. Por isto, os arquivos de acesso aleatório são conhecidos também como arquivos de acesso direto. Muitas técnicas podem ser usadas para organizar arquivos de acesso direto. A mais simples é exigir que todos os registros do arquivo sejam de mesmo tamanho(em bytes). Com registros de tamanho fixo é possível calcular a posição de qualquer registro em relação ao início do arquivo. Isto permite acessar diretamente um registro específico do arquivo, qualquer que seja o número de registros no arquivo.

w Dentre as informações mantidas para acessar os dados de um arquivo, uma émuito importante: o ponteiro que identifica o registro a ser acessado. Na abertura do arquivo, com a função fopen(), este ponteiro é posicionado no início do primeiro registro.

último registro...registro 4registro 3registro 2registro 1

Page 10: JavaScript - Aula08

ELFS, 2003 192

Tratamento de Arquivos

w Cada acesso (de leitura ou de gravação) desloca este ponteiro de uma quantidade de bytes igual ao tamanho de um registro, ou seja, desloca o ponteiro para o início do próximo registro. Quando este ponteiro estiver posicionado além do último registro, a função feof() retorna 1.

w Em PHP é possível posicionar o ponteiro de arquivo em um registro específico com a função int fseek(int id, int desloc, int ref), onde id é um identificador de arquivo, desloc é um deslocamento (em bytes) a partir da referência ref, que pode ser: SEEK_SET (início do arquivo), SEEK_CUR (posição atual do ponteiro) ou SEEK_END (final do arquivo). Note que se a referência for SEEK_END, desloc deve ser um valor negativo, pois uma tentativa de avançar o ponteiro para além do fin do arquivo (eof) resulta em erro. A função retorna 0 em caso de sucesso; caso contrário, retorna -1.

w Exemplo: Considere um arquivo, com registros de mesmo tamanho, contendoo número, o nome e a nota de alunos. Deseja-se um script que permita listar o conteúdo do arquivo ou modificar a nota de um aluno. Considere que este script é chamado a partir da página:

1#Maria Silva #8.82#João Pereira #7.63#Pedro Alvares #5.04#José Ribamar #9.55#Ana Ferreira #7.9

Page 11: JavaScript - Aula08

ELFS, 2003 193

Tratamento de Arquivos

<?php

function completa($s,$tam){while (strlen($s) < $tam)$s = $s . " ";

return $s;}

function separa($linha,&$num,&$nome,&$nota){$pos = strpos($linha, "#");$num = substr($linha, 0, $pos);$linha = substr($linha, $pos+1, TAMREG);$pos = strpos($linha, "#");$nome = substr($linha, 0, $pos);$nota = substr($linha, $pos+1, TAMREG);

}

function listar(){echo('<table border="1"><thead style="background-color:yellow">'.

'<tr><th>Num</th><th>Nome</th><th>Nota</th></tr></thead>'.'<tbody align="center">');

if ($arq = fopen("alunos.txt","r")) {while (!feof($arq)) {

aula08_06.php

Note que os três últimos parâmetros da função separa são passados por referência, ou seja, os valores destes parâmetros ao final da execução da função irão substituir os valores dos parâmetros correspondentes usados na chamada da função. No cabeçalho da função, os parâmetros passados por referência devem ser precedidos pelo símbolo &.

TAMREG é uma constante definida no script principal.

Page 12: JavaScript - Aula08

ELFS, 2003 194

Tratamento de Arquivos

$linha = fgets($arq,TAMREG);separa($linha,$num,$nome,$nota);echo("<tr><td>$num</td><td>$nome</td><td>$nota</td></tr>");

}

fclose($arq);echo("</tbody></table>");

}elseecho("<h2>Arquivo alunos.txt não localizado!</h2>");

}

function pegar_nota(){header("Location: http://localhost/DAIaula08/aluno.htm");

}

function modificar($num_aluno,$nova_nota){if ($arq = fopen("alunos.txt","r+")) {$desloca = (TAMREG+1)*($num_aluno-1);fseek($arq,$desloca,SEEK_SET);$linha = fgets($arq,TAMREG);separa($linha,$num,$nome,$nota); $nome_aluno = completa($nome, 22);fseek($arq,$desloca,SEEK_SET);fwrite($arq, " ".$num_aluno."#".$nome_aluno."#".$nova_nota);fclose($arq);

Note que a função pegar_nota carrega uma nova página: aluno.htm

Uma chamada à função fseek deve ser feita antes de um acesso de leitura ou de um acesso de escrita, para posicionar o ponteiro no registro correto.

Page 13: JavaScript - Aula08

ELFS, 2003 195

Tratamento de Arquivos

echo("<h3>Modificada a nota do aluno $num_aluno"."(de $nota para $nova_nota)</h3>");

}elseecho("<h2>Arquivo alunos.txt não localizado!</h2>");

}

// *********************************// Script principal// *********************************

define(TAMREG, 31);

switch ($Opcao){case "1": listar();break;

case "2": pegar_nota();break;

case "3":modificar($num_aluno,$nova_nota);break;

}?>

No caso de $Opcao ser igual a 2, antes de modificar a nota é preciso exibir a página abaixo (aluno.htm), para que o usuário possa especificar o número do aluno e a nova nota.

Page 14: JavaScript - Aula08

ELFS, 2003 196

Tratamento de Arquivos

w Considere que a opção Modificar da página principal (aula08_06.htm) deve chamar a página aluno.htm onde o usuário deverá indicar o número e a nova nota do aluno. Os códigos dessas páginas podem ser:

<html><head><title>Controle de Notas</title></head><body><h2>Controle de Notas</h2><form action="aula08_06.php" method="post"> <input type="radio" name="Opcao" value="1" checked>Listar</input><br><input type="radio" name="Opcao" value="2">Modificar</input><br><br><input type="submit" value="Executar"></form></body></html>

aula08_06.htm

<html> <body> <form action="aula08_06.php?Opcao=3" method="post"> Num: <input type="text" name="num_aluno" size="5"><br>Nota: <input type="text" name="nova_nota" size="5"><br><br><input type="submit" value=" OK "> </form> </body> </html>

aluno.htm

Page 15: JavaScript - Aula08

ELFS, 2003 197

Tratamento de Arquivos

w Exercício. Modifique o script aula08_06.php de modo a considerar também a operação de inclusão de novos alunos no arquivo.

w Exercício. Considere que um banco armazena em arquivo as seguintes informações de seus clientes: número da conta, nome do cliente, limite de crédito, saldo atual. Este banco deseja implementar um programa para atendimento eletrônico que permita aos clientes executarem as seguintes ações: abertura de conta, listagem de saldo, depósito e saque. Considere que os números das contas são sequenciais a partir de 1. Escreva um script PHP para implementar estas ações. Note que a operação de saque deve levar em conta o limite de crédito (ou seja, o limite de saldo negativo) do cliente. Considere as seguintes interfaces com o usuário:

Note que na interface de Abertura de conta, o número da conta deve ser estabelecido pelo script (a caixa de texto deve estar desabilitada).