domingo, 28 de setembro de 2008

Conversão de Caracteres para HTML Entities

Recentemente recebi um layout em HTML com os textos usando acentuação: á é í ó ç e etc. Quando colocado no browser tive problemas para exibir esses caracteres corretamente, eles apareciam de forma ilegível.

Como eu estou no linux, não tenho como usar os recursos de softwares proprietários dreamweaver, editplus e etc que já fazem a conversão dos caracteres especiais para os chamados HTML Entities. Procurando na rede, descobri um projeto open-source no sourceforge chamado HTMLEntities que consiste em um conjunto de classes em java para fazer esse tipo de conversão.

Para baixar os códigos fontes e o jar já compilado do projeto, visite o endereço: http://sourceforge.net/projects/htmlentities/

Depois de adicionar o jar do HTMLEntities no seu projeto Java, é possível acessar os recursos de conversão de caracters por meio de uma classe estática. Veja um exemplo simples de conversão de caracteres acentuados para HTML Entities (SimpleConvert.java):

package com.htmlentity;
import com.tecnick.htmlutils.htmlentities.HTMLEntities;

public class SimpleConvert {

public static void main(String[] args) {
String text = "substituição de caracteres: á é í ó ú ç";

String html = HTMLEntities.htmlentities(text);

System.out.println("Caracteres convertidos: " + html);
}
}

O método htmlentities(String) da classe HTMLEntities é chamado estaticamente, reliza a corversão do texto passado como parâmetro e retorna o novo resultado (Linha 8 do código).

Essa conversão é util para desenvolvedores que necessitam colocar esse tipo de funcionalidade dentro de seus projetos java, ou mesmo webdesigners que precisam codificar seus textos em forma de HTML Entities.

segunda-feira, 22 de setembro de 2008

Java: Medir tempo de execução de tarefas

Com a necessidade de medir o desempenho de uma determinada classe, criei um cronômetro simples. Acredito que seja um código facilmente encontrado na rede, mas esse é bem optimizado e de fácil utilização.

O cronômetro é uma classe estática chamada Chronometer.java:


/**
* @author J.P. Eiti Kimura Classe para cronometrar
* operações em Java
*/
public final class Chronometer {

private static long startValue;
private static long stopValue;
private static long timeDiff;

/**
* Inicia a contagem temporal
*/
public static void start() {
startValue = System.currentTimeMillis();
stopValue = 0;
timeDiff = 0;
}

/**
* Calcula a diferença temporal
*/
public static void stop() {
stopValue = System.currentTimeMillis();
timeDiff = stopValue - startValue;
}

/**
* Retorna o diferença de tempo medida
* @return tempo em milisegundos
*/
public static long elapsedTime() {
return timeDiff;
}
}


A classe é basicamente formada por métodos estáticos de inicio de contagem de tempo (linha 14), de termino da contagem e cálculo do tempo (linha 23), e por fim, um método que retorna o valor do tempo medido (linha 32).

Para exemplificar a utilização da classe Chronometer, vamos medir o tempo gasto para efetuar duas tarefas usando recursos diferentes.

Imagine uma situação onde se deseja concatenar uma cadeia de caracteres qualquer um número definido de vezes. Qual objeto java seria mais rápido para fazer essa tarefa, um simples String, ou um StringBuffer? Para responder essa questão vamos medir o desempenho com nossa classe de cronômetro.

ChonoTest.java


public class ChronoTest {

public static void main(String[] args) {

StringBuffer sb = new StringBuffer();
String sValue = "";

long time1 = 0;
long time2 = 0;

// mede tempo da primeira operação
Chronometer.start();
for (int i = 0; i < 5000; i++) {
sb.append("It's measure time!");
}
Chronometer.stop();
time1 = Chronometer.elapsedTime();

// mede tempo da segunda operação
Chronometer.start();
for (int i = 0; i < 5000; i++) {
sValue += "It's measure time!";
}
Chronometer.stop();
time2 = Chronometer.elapsedTime();

System.out.println("StringBuffer result:" + time1 + "ms");
System.out.println("String result:" + time2 + "ms");

}
}


Note que inicialmente, utilizou-se a classe de cronômetro para a marcar o tempo gasto para concatenar 5000 vezes a frase "It's measure time!" (linha 12). Após a concatenação, o cronômetro é parado (linha 16) e o tempo é calculado (linha 17).

Executando a classe ChronoTest.java em um computador com processador Core2 Quad, com 2GB de memória RAM obtive o seguinte resultado:

StringBuffer result:16ms
String result:7586ms


Esse pequeno exemplo mostra como é possível calcular o tempo gasto em determinadas operações, pode ser aplicado para verificar o tempo gasto do retorno de um conjunto de dados de um banco de dados por exemplo, e mesmo para identificar qual parte do processamento de uma tarefa é a mais custosa em tempo.

quinta-feira, 18 de setembro de 2008

Programas para Compactação/Descompactação de Arquivos

Após instalar o Ubuntu Linux 8.04, verifiquei a necessidade de instalar alguns softwares para compactar/descompactar arquivos em formatos diversos, zip, rar, tar, gz, 7zip e etc.

A linha de comando abaixo instala uma série de pacotes para resolver esse problema:

sudo aptitude -y install unace rar unrar zip unzip \
p7zip-full p7zip-rar sharutils aish uudeview mpack \
lha arj cabextract file-roller

segunda-feira, 15 de setembro de 2008

Recompilar FFMPEG com suporte para MP3, AAC e AMR

O FFmpeg

O FFmpeg é uma ferramenta completa para gravar, converter e efetuar streaming de audio e vídeo. Inclui a libavcodec, uma poderosa biblioteca de codecs para audio e vídeo. O FFmpeg é desenvolvido no linux, mas pode ser compilado na maioria dos sistemas operacionais, incluindo o Windows.

Na última compilação do FFmpeg, não estava habilitado o suporte à medias em formato mp3, aac e amr. Esse tutorial mostra como recompilar o FFmpeg habilitando o surporte à esses formatos de mídia. O tutorial foi testado no ubuntu linux versão 8.04.1, no entando com algumas modificações pode facilmente ser adaptado para compilar o software em outros sistemas.

Para copiar os códigos fonte diretamente do site do cvs, utilizei o subversion. Para instalar o subversion digite no terminal:


sudo apt-get install subversion



Para organizar nosso processo, sugiro criar o diretório /proj em /tmp que conterá o código fonte do ffmpeg e dos codecs para compilação:

cd /tmp
mkdir proj



O próximo passo é fazer o download do código fonte do ffmpeg:

svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg


ou

wget http://ffmpeg.mplayerhq.hu/ffmpeg-export-snapshot.tar.bz2



Vamos descompactar o arquivo com os fontes e renomear a pasta original para ffmpeg:

sudo tar -jxvf ffmpeg-export-snapshot.tar.bz2
mv ffmpeg-export-snapshot ffmpeg




Bibliotecas e Dependências

Antes de compilar o ffmpeg, verifiquei a necessidade de softwares adicionais para que a compilação possa se dar corretamente. Para compilar, é necessário ter um compilador C/C++ instalado e algumas outras bibliotecas para auxiliar na compilação. Lembrando que no meu caso, estou executando os procedimentos no ubuntu linux, verifique a necessidade de instalar essas bibliotecas no seu sistema.

Instalando o g++ (~32MB) 4.2.3:

sudo apt-get install g++



Instalando o comando patch (2.5.9.4):

sudo apt-get install patch



Instalando pacotes autotools:

sudo apt-get install automake (autoconf automake m4)
sudo apt-get install libtool ( autotools-dev libtool )
sudo apt-get install yasm ( autotools-dev libtool )



Demais pacotes:

sudo apt-get install build-essential


Feita a instalação das ferramentas, vamos iniciar a compilação do ffmpeg propriamente dito. Antes de instalar as bibliotecas auxiliares, vamos compilar o código fonte original do ffmpeg para garantir que a configuração das bibliotecas e mesmo a integridade do código fonte esteja ok:

cd /tmp/proj/ffmpeg
sudo ./configure
make
make install


Se tudo correu bem até aqui, um arquivo binário chamado ffmpeg deve ter sido gerado. É o nosso programa já compilado no formato original.


Bibliotecas Externas (codecs)

Sugiro que seja criada uma pastas codecs em /tmp/proj para que os códigos fonte das bibliotecas externas sejam armazenados, em seguida criar uma pasta chamada lib em /tmp/proj para que sejam armazenadas as bibliotecas compiladas.

- mp3lame:
-----------------

Download do código fonte para a pasta /tmp/proj/codecs:
http://prdownloads.sourceforge.net/lame/lame-3.97.tar.gz?download

Descompactar e mover para a pasta dos fontes do ffmpeg:

cd /tmp/proj/codecs
tar xvfz lame-3.97.tar.gz
mv lame-3.97 ../ffmpeg



baixar o patch de correção para o diretório /tmp/proj/codecs e mover para a pasta /tmp/proj/ffmpeg/lame-3.97:

wget http://arrozcru.no-ip.org/ffmpeg_patches/lame.diff



no diretório /tmp/proj/ffmpeg/lame-3.97, aplique o patch de correção:

patch -p0 < ../lame.diff


Para compilar o mp3lame, gerando as libs no diretório /tmp/proj/lib:

./configure --prefix=/tmp/proj/lib --disable-shared --enable-static --disable-frontend --enable-yasm
make
make install




- faad2
----------

Download do código fonte para a pasta /tmp/proj/codecs:
http://prdownloads.sourceforge.net/faac/faad2-2.6.1.tar.gz?download

baixar o patch de correção para o diretório /tmp/proj/codecs e mover para a pasta /tmp/proj/ffmpeg:

wget http://arrozcru.no-ip.org/ffmpeg_patches/faad2-2.6.1.patch



Descompactar e mover para a pasta ffmpeg:

tar xvfz faad2-2.6.1.tar.gz
mv faad2 ../ffmpeg



no diretório /tmp/proj/ffmpeg, aplique o patch de correção:

patch -p0 < faad2-2.6.1.patch



Compilar o faad2, gerando as libs no diretório /tmp/proj/lib:

cd faad2
sh bootstrap
./configure --prefix=/tmp/proj/lib --enable-static --disable-shared
make LDFLAGS="-no-undefined"
make install



- faac
-----------

Download do código fonte para a pasta /tmp/proj/codecs:
http://prdownloads.sourceforge.net/faac/faac-1.26.tar.gz?download

Descompactar e mover para a pasta ffmpeg:

tar xvfz faac-1.26.tar.gz
mv faac ../ffmpeg



baixar o patch de correção para o diretório /tmp/proj/codecs e mover para a pasta /tmp/proj/ffmpeg:
wget http://arrozcru.no-ip.org/ffmpeg_patches/faac-1.26.patch

no diretório /tmp/proj/ffmpeg, aplique o patch de correção:

patch -p0 < faac-1.26.patch



Compilar o faac, gerando as libs no diretório /tmp/proj/lib

cd faac
sh bootstrap
./configure --prefix=/tmp/proj/lib --enable-static --disable-shared
make LDFLAGS="-no-undefined"
make install



- amr_nb
-----------

É necessário o unzip e o wget para instalação desse codec, assim como acesso a Internet.

Download do código fonte para a pasta /tmp/proj/codecs:
http://ftp.penguin.cz/pub/users/utx/amr/amrnb-7.0.0.0.tar.bz2

Descompactar e mover para a pasta ffmpeg:

tar -jxvf amrnb-7.0.0.0.tar.bz2
mv amrnb-7.0.0.0 ../ffmpeg



Compilar o amr_nb, gerando as libs no diretório /tmp/proj/lib

cd amrnb-7.0.0.0
./configure --prefix=/tmp/proj/lib --enable-static --disable-shared
make
make install



- amr_wb
-----------

É necessário o unzip e o wget para instalação desse codec, assim como acesso a Internet.

Download do código fonte para a pasta /tmp/proj/codecs:

wget http://ftp.penguin.cz/pub/users/utx/amr/amrwb-7.0.0.2.tar.bz2



Descompactar e mover para a pasta ffmpeg:

tar -jxvf amrwb-7.0.0.2.tar.bz2
mv amrwb-7.0.0.2 ../ffmpeg



Compilar o amr_wb, gerando as libs no diretório /tmp/proj/lib

cd amrwb-7.0.0.2
./configure --prefix=/tmp/proj/lib --enable-static --disable-shared
make
make install



Recompilar FFmpeg usando codecs já compilados

Para recompilar o ffmpeg, deve-se indicar os codecs que serão adicionados no ./configure e também o caminho dos includes e libs dos codecs:

./configure --enable-libmp3lame --enable-libfaad --enable-gpl --enable-libfaac --enable-gpl --enable-libamr-nb --enable-nonfree --enable-libamr-wb --enable-nonfree -extra-ldflags=-L/tmp/proj/lib/lib --extra-cflags=-I/tmp/proj/lib/include
make
make install



Desse forma geramos uma nova versão do ffmpeg com suporte a audio mp3, aac e amr.

Para maiores detalhes consulte:
http://arrozcru.no-ip.org/ffmpeg_wiki/tiki-index.php?page=HomePage

Para detalhes de como recompilar o ffmpeg especificamente para o ubuntu linux, esse endereço oferece uma descrição detalhada:
https://wiki.ubuntu.com/ffmpeg

quinta-feira, 11 de setembro de 2008

Sistema de Busca Off-line

Meu amigo me pediu uma ajuda para fazer um sistema de busca off-line. Entende-se off-line como um sistema de busca que pode ser executado de dentro de um cd/pen-drive sem que fosse necessário ter um servidor e/ou banco de dados para isso. O sistema deveria ser multiplataforma também.

Para ilustrar, vamos imaginar um sistema que busque dados de artigos acadêmicos em uma mídia qualquer e os dados são obtidos a partir de um arquivo de dados.

Para resolver esse problema, utilizei um sitema feito em javascript que roda a partir do navegador web. A estrutura dos arquivos deve ser conforme a figura ao lado. Uma pasta raiz chamei de busca_offline com um diretório de scripts, um arquivo de dados (base.dat) e um index.html para apresentação do resultado.

O sistema se baseia em uma chamada via HttpRequest, carregando o arquivo com os dados base.dat; a partir de então a busca é feita sobre o arquivo carregado utilizando-se expressões regulares.

O arquivo de dados base.dat é do tipo texto (codificado em UTF-8), com os campos de interesse separados pelo caracter #:

base.dat

João Paulo Eiti Kimura#Programas para busca OFF-LINE
Alcides Ribeiro Jr.#Testes e experimentações com algebra
Zulaide Ribeiro da Silva#Ultra-som de potência para Terapia
José da Silvã# AJAX e suas maravilhas com Javascript
Márcia Kímura# Técnica Marcação de orgãos em Radioterapia
Paulo Antônio Machado# Java EE Segunda Edição
Roberto Pereira de Melo# Programação Orientada a Eventos
Flavia Renata de Souza# Medidor de Fluxo sanguíneo
Roberto Murari# Recursos Humanos e marketing


O Javascript responsável por carregar o arquivo de dados e efetuar as buscas é mostrado a seguir.

engine.js

1 var objArray;
2 var respText;
3
4 /* carrega o arquivo de dados*/
5 function loadResources()
6
{
7 AJAXRequest();
8 }
9
10 /* faz o parser do arquivo lido separando por linhas */
11 function parseResponse(responseText)
12
{
13 objArray = responseText.split("\n");
14 data = "";
15
16 for(i = 0; i < objArray.length; i++){
17 data+= i + " = " + objArray[i].split("#") + "\n";
18 }
19
20 document.getElementById("sresult").value = data;
21
22 }
23
24 /* ajusta os parâmetros adicionando acentuação nas buscas */
25 function adjustParam(param)
26
{
27 param = param.replace(/[aãâáà]/gi, "[aãâáà]");
28 param = param.replace(/[eêéè]/gi, "[eêéè]");
29 param = param.replace(/[iíì]/gi, "[iíì]");
30 param = param.replace(/[oôóò]/gi, "[oôóò]");
31 param = param.replace(/[uúùü]/gi, "[uúùü]");
32
33 param = param.replace(/[cç]/gi, "[cç]");
34
35 return param;
36 }
37
38 /* efetua uma busca em todos os elementos do vetor */
39 function doSearch(param)
40
{
41 param = adjustParam(param);
42 var found = false;
43 var links = "";
44
45 //percorre todos os registros
46 for(i = 0; i < objArray.length; i++){
47
48 var pattern = new RegExp(param,"gi");
49
50 var str = objArray[i];
51 found = pattern.exec(str);
52
53 if (found)
54 {
55 links += "<div > <a href='#'>" + str.split("#") + "</a></div>";
56 }
57
58 }
59
60 document.getElementById("resultArea").innerHTML = links;
61 }
62
63 /* Esse método instancia o objeto XMLHttpRequest*/
64 function GET_XMLHTTPRequest()
65
{
66 var request;
67
68 // Lets try using ActiveX to instantiate the XMLHttpRequest object
69 try{
70 request = new ActiveXObject("Microsoft.XMLHTTP");
71 }catch(ex1){
72 try{
73 request = new ActiveXObject("Msxml2.XMLHTTP");
74 }catch(ex2){
75 request = null;
76 }
77 }
78
79 // check if it supports httprequest
80 if(!request && typeof XMLHttpRequest != "undefined"){
81 //The browser does, so lets instantiate the object
82 request = new XMLHttpRequest();
83 }
84
85 return request;
86 }
87
88
89 function AJAXRequest()
90
{
91 //instancia objeto
92 var myXMLHttpRequest = GET_XMLHTTPRequest();
93
94 //Make sure the XMLHttpRequest object was instantiated
95 if (myXMLHttpRequest)
96 {
97 //carrega o arquivo de dados
98 myXMLHttpRequest.open("GET", "base.dat", true);
99
100 //função que trata a requisição quando o request termina
101 myXMLHttpRequest.onreadystatechange = function (aEvt) {
102
103 if(myXMLHttpRequest.readyState == 4){
104 parseResponse(myXMLHttpRequest.responseText);
105 }
106 };
107 myXMLHttpRequest.send(null);
108 }
109 else
110 {
111 //Oh no, the XMLHttpRequest object couldn't be instantiated.
112 alert("A problem occurred instantiating the XMLHttpRequest object.");
113 }
114 }



O método doSearch(linha 39) faz a busca de um determinado texto no campos do arquivo de dados carregado. O método adjustParam(linha 25), utiliza expressões regulares para ajustar os parâmetros da busca de forma que sejam ignorados os caracteres acentuados.

O código do arquivo index.html de apresentação dos dados é mostrado abaixo.

index.html


1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
4 <title>Busca offline</title>
5 <script src="script/engine.js" type="text/javascript"></script>
6 </head>
7 <body onload="javascript:loadResources();">
8
9 <h1>Busca Off-line</h1>
10 <br />
11
12 <input type="text" id="fsearch"> &nbsp;
13 <button name="btnsearch" value="Search"
14 onclick=
"javascript:doSearch(document.getElementById('fsearch').value);">

15 Search </button>
16 <br/><br/>
17
18 <div>
19 <textarea rows="10" cols="70" id="sresult"></textarea>
20 </div>
21 <br/><br/>
22
23 <h1> Resultado </h1>
24 <div id="resultArea">
25 </div>
26 </body>
27 </html>



Quando a página html é carregada, o arquivo de dados também é carregado na memória (linha 7). Nessa página, temos um campo para busca, um botão search (linhas 13,14 e 15) que irá chamar a engine de busca.

Por conveniência criei um textarea para exibir os dados que foram carregados do arquivo (linha 19). E, por fim, uma div que irá exibir os resultados da nossa busca (linha 24).
A figura abaixo mostra como fica a apresentação da engine de busca off-line:


No caso da imagem de exemplo, foi efetuada uma busca pela palavra terapia. Note que o os resultados que retornara foram referentes as palavras: Terapia e Radioterapia.

Para alterar os links do resultado, basta alterar a linha 55 do arquivo engine.js. Essa micro-engine de busca pode ser utilizada totalmente off-line, colocada dentro de um pen-drive, CD ou DVD. Tem a vangatem de ser multiplataforma e usa ferramentas livres de licença.

Download do código fonte: busca_offline.zip

segunda-feira, 8 de setembro de 2008

Instalando o AWN no Ubuntu Hardy Haron 8.04

Link para este post no Dicas-L: http://www.dicas-l.com.br/dicas-l/20080506.php

O Avant Window Navigator, conhecido como AWN, é uma barra do tipo dock que após ser ativada fica localizada no canto inferior da tela. O AWN suporta atalhos, lista de tarefas e applets de terceiros, tem aparência configurável que lembra as barras de menus dos sistemas da Apple. É uma boa opção para deixar o GNOME com um aspecto diferente quanto a interação com usuario. ;)

Para instalar o AWN na nova versão do Ubuntu Hardy Haron: devemos primeiro adicionar os repositórios nas listas de source, para fazer isso vai interface gráfica acesse menu: System -> Administration -> Software Source

Em seguida clique sobre a guia "Third-Party Software" e adicione os seguintes repositórios (adicione uma linha por vez):

deb http://ppa.launchpad.net/awn-testing/ubuntu hardy main
deb-src http://ppa.launchpad.net/awn-testing/ubuntu hardy main

Clique em "Close" para fechar a janela principal e confirme a opção para recarregar os repositórios clicando em "Reload" e guarde até que a janela fechar.

Acesse o terminal: Applications -> Accessories -> Terminal e digite a seguinte linha de comando para iniciar a instalação do AWN:

sudo apt-get install awn-manager-trunk awn-extras-applets-trunk

Após a instalação, o AWN pode ser iniciado através do menu:

Applications -> Accessories -> Avant Window Navigator

Para adicionar mais links ao dock, basta arrastar os links dos menus do GNOME sobre o dock do AWN que os links são criados automaticamente. Além dos links é possível adicionar applets de leitura de RSS, previsão do tempo, recursos de hardware, menus do sistema e etc.

Vejam um exemplo do dock configurado:

Post de Inauguração

Olá Pessoal,

Está aberto o blog onde vou registrar pequenos códigos, dicas e notas de desenvolvimento utilizando sistemas open-source, em especial tecnologia JAVA usando sistemas linux.

Grande Abraço,