Antes de empezar a documentar este post recuerdo la vez que quería escribir y leer dbf desde java, empece buscando por Internet pero no había mucha documentación disponible hasta que encontré algo y lo voy a replicar por si a alguien mas le sirve ya sea para migrar sus bases de datos.
Aquí les va la url:
http://sarovar.org/docman/view.php/32/23/javadbf-tutorial.html
Aunque esta en ingles me he tomado la molestia de traducirlo en este post para aquellos que no son muy bilingues
Tutorial de la libreria JavaDBF
(for JavaDBF ver. 0.4.0 and above)
Anil Kumar K.
anil at linuxense dot com
Linuxense Information Systems Pvt. Ltd., Trivandrum, India
1. Introducción
JavaDBF es una librería para leer y escribir archivos XBase. Estos son bastantes en aplicaciones legales alrededor de los dbf como su primer formato de almacenamiento. JavaDBF fue inicialmente escrito para transferir datos con aplicaciones. Algo más que, hay requerimientos para exportar datos desde una aplicación java a hojas de calculo como Excel o Lotus 123. Un archivo DBF debe ser mas apropiado en otras situaciones como son el CSV o un archivo HTML porque un archivo DBF puede llevar campos de tipo de información. Mas sobre, formato XBase es como un Open-standard; esto es entendible por casi todos los programas de hojas de calculo.
2. Obteniendo e Instalando
Obtener la ultima versión de JavaDBF desde http://sarovar.org/projects/javadbf/. Crear una carpeta en una ubicación conveniente y hacerlo correr:
tar xvfz javadbf-x.x.x-tar.gz cd javadbf-x.x.x
En esta carpeta encontraras javadbf.jar que contiene la librería. Incluye este archivo jar en su variable $CLASSPATH variable. Entonces estas listo para avanzar.
3. Resumén de la librería
JavaDBF tiene un simple API propio y no implementa el API JDBC. Es diseñado así porque JavaDBF no esta incluido en el soporte del estilo de interacción con RDBMS. Si estas presumiendo usarlo como un back-end; Simplemente no trabaja de esa forma . Entonces, JavaDBF no es diseñado para hilos seguros; tenlo en mente cuando diseñes aplicaciones de hilos . JavaDBF viene en el paquete com.linuxense.javadbf. Importa ese paquete en tu código java. Los siguientes ejemplos te familiarizaran con este API.
3.1. Tipo de Datos
En la versión 0.3.2, JavaDBF suporta casi todos los tipos de datos XBase excepto el campo Memo. Mientras lee, esos tipos de datos son interpretados como tipo de datos de java apropiados. La siguiente tabla muestra el esquema de datos.
XBase Type | XBase Symbol | Java Type used in JavaDBF |
---|---|---|
Character | C | java.lang.String |
Numeric | N | java.lang.Double |
Double | F | lava.lang.Double |
Logical | L | java.lang.Boolean |
Date | D | java.util.Date |
4. Leer un archivo DBF
Al leer un archivo DBF, JavaDBF provee una clase DBFReader. Lo siguiente esta listo para compilar, el programa se explica describiendo casi todas las características de la clase DBFReader
. Copiar/Pegar el listado y compilarlo. Manten un archivo .dbf
manejable al pasarlo a este programa como un argumento. (Es decir algo que puedas leer, que este a tu alcance).
import java.io.*;
import com.linuxense.javadbf.*;
public class JavaDBFReaderTest {
public static void main( String args[]) {
try {
// create a DBFReader object
//
InputStream inputStream = new FileInputStream( args[ 0]); // take dbf file as program argument
DBFReader reader = new DBFReader( inputStream);
// get the field count if you want for some reasons like the following
//
int numberOfFields = reader.getFieldCount();
// use this count to fetch all field information
// if required
//
for( int i=0; i<numberOfFields; i++) {
DBFField field = reader.getField( i);
// do something with it if you want
// refer the JavaDoc API reference for more details
//
System.out.println( field.getName());
}
// Now, lets us start reading the rows
//
Object []rowObjects;
while( (rowObjects = reader.nextRecord()) != null) {
for( int i=0; i<rowObjects.length; i++) {
System.out.println( rowObjects[i]);
}
}
// By now, we have itereated through all of the rows
inputStream.close();
}
catch( DBFException e) {
System.out.println( e.getMessage());
}
catch( IOException e) {
System.out.println( e.getMessage());
}
}
}
5. Escribiendo un archivo DBF
La clase complementaria a DBFReader
es el DBFWriter
. Mientras creas un archivo de datos .dbf
tendras que tratar con dos aspectos: 1. definir los campos y 2. poblar o abastecer datos. Como mencione antes un campo dbf es representado por la clase DBFField
. Primero dejame familiarizarte con esta clase.
5.1. Definiendo Campos
Crear un objeto de la clase DBFField
:
DBFField field = new DBFField(); field.setField( "emp_name"); // give a name to the field field.setDataType( DBFField.FIELD_TYPE_C); // and set its type field.setFieldLength( 25); // and length of the field
Bien, ahora un completo objeto DBFField
listo para usar. Tenemos creados muchos objetos DBFField
como nosotros deseemos en el archivo de datos .dbf
. La clase DBFWriter
acepta DBFField
en un arreglo. Ahora, nos moveremos al próximo paso que sera abastecer de datos o llenarlo con datos.
5.2. Preparando el Objeto DBFWriter
Un DBFWriter
es usado para crear un archivo .dbf
. Primero crearemos un objetos DBFWriter
llamándolo desde su constructor y entonces seteamos sus campos a crear (como esta explicado arriba) llamando con el método setFields
.
DBFWriter writer = new DBFWriter();writer.setFields( fields); // fields is a non-empty array of DBFField objects
Ahora, el objeto DBFWriter
esta listo para ser llenado. El método para agregar datos al DBFWriter
es addRecord
y toma un objeto array como argumento. Este objeto array es el que supuestamente contiene los valores para los campos agregados uno a uno correspondiente al campo seteado o declarado anteriormente.
Lo siguiente es un programa completo explicando los pasos descritos en la parte anterior:
import java.io.*;
public class DBFWriterTest {
public static void main( String args[])
throws DBFException, IOException {
// let us create field definitions first
// we will go for 3 fields
//
DBFField fields[] = new DBFField[ 3];
fields[0] = new DBFField();
fields[0].setName( «emp_code»);
fields[0].setDataType( DBFField.FIELD_TYPE_C);
fields[0].setFieldLength( 10);
fields[1] = new DBFField();
fields[1].setField( «emp_name»);
fields[1].setDataType( DBFField.FIELD_TYPE_C);
fields[1].setFieldLength( 20);
fields[2] = new DBFField();
fields[2].setField( «salary»);
fields[2].setDataType( DBFField.FIELD_TYPE_N);
fields[2].setFieldLength( 12);
fields[2].setDecimalCount( 2);
DBFWriter writer = new DBFWriter();
writer.setFields( fields);
// now populate DBFWriter
//
Object rowData[] = new Object[3];
rowData[0] = «1000»;
rowData[1] = «John»;
rowData[2] = new Double( 5000.00);
writer.addRecord( rowData);
rowData = new Object[3];
rowData[0] = «1001»;
rowData[1] = «Lalit»;
rowData[2] = new Double( 3400.00);
writer.addRecord( rowData);
rowData = new Object[3];
rowData[0] = «1002»;
rowData[1] = «Rohit»;
rowData[2] = new Double( 7350.00);
writer.addRecord( rowData);
FileOutputStream fos = new FileOutputStream( args[0]);
writer.write( fos);
fos.close();
}
}
Ten en mente que todavia el metodo write es llamado, y todos los datos agregados seran mantenidos en memoria. Entonces, si tu estas planeando escribir un gran monto de datos asegurate que sea seguro ponerlos en memoria hasta que sean escritos a disco y el objeto DBFWriter
es garbage-collected. Leer la sección «Sync Mode» para saber como JavaDBF usa una especial caracteristica sobre esto.
5.3. «Sync Mode» –Escribiendo registros a archivos como son agregados
Este es muy usado cuando JavaDBF es usado para crear un DBF con un gran número de registros. En este modo, el mantener registros en memoria para escribir todos en una sola, registros son escritos al archivo como addRecord()
es llamado. Aqui esta como escribir en modo Sync Mode:
Crear una instancia DBFWriter pasándole un objeto File
que representa uno nuevo/ no existente o archivo vacio. Y lo has hecho! Pero, como en el modo normal, recuerda llamar a write()
cuando tengas agregados todos los registros. Esto ayuda a JavaDBF a escribir los meta datos con los valores correctos. Aquí un código de ejemplo:
import com.linuxense.javadbf.*;import java.io.*;public class DBFWriterTest { public static void main( String args[]) throws DBFException, IOException { // ... DBFWriter writer = new DBFWriter( new File( "/path/to/a/new/file")); /* this DBFWriter object is now in Syc Mode */ // ... } }
7. Agregando Registros
Desde la version 0.4.0 JavaDBF suporta agregar registros a un archivo DBF existente. Usa el mismo constructor usado en Sync Mode para alcanzar esto. Pero el objeto file pasado al constructor debe representarse por el archivo dbf que los registros seran agregados.
Es ilegal llamar setFields
en un objeto DBFWriter creado para agregar datos. Aquí también se requiere llamar el método write después de agregar todos los registros.
6.Características Planeadas
- Soporte para campos memo.
ey, muchas gracias! 🙂
hey que buen tutorial, pero aun tengo una duda, si yo imprimo los dato de un .DBF se imprimen en bloques ta cual los lee de la dase de datos, pero si quiero separlos uno por uno debo crear una estructura especial??? o como es la mejor forma d hacerlo???
Como lo puedes ver en el ejemplo todos se leen con un índice.
me refiero a:
Object []rowObjects;
while( (rowObjects = reader.nextRecord()) != null) {
for( int i=0; i<rowObjects.length; i++) {
System.out.println( rowObjects[i]);
}
}
Se me ocurre que podrías crearte un modelo es decir:
tienes en la tabla el id y el nombre
Entonces al momento de leer tu sabrías que
setId(rowObject[0]);
setNombre(rowObject[1]);
Entonces los leerias por separado.
Bueno eso es lo que se me ocurre al vuelo.
Como puedes observar el índice establece que dato lees.
Espero haber contestado tu inquietud de alguna manera.
Saludos y Buena suerte
Muchas gracias por la respuesta. Me vas solucionado un gran problema, ahora como todo cuando trabajas en java cuando resuelves algo te sale un nuevo problema. El DBFReader se comprta muy bien con archivos normales pero cuando tienen demasiados registros se guinda osea se queda pegado, se te ha presentado alguna ves eso??? es decir tendras una solucion para ello????
Gracias nuevamente y Exito
Hola
Como puedes ver el acceso a los datos es secuencial es decir uno a uno entonces se dará un poco la demora.
Pero algo que puedes hacer es optimizar el código me refiero a que si estas utilizando por ejemplo, empezar por sacar la comprobacion de longitud del for para que no se ejecute cada vez es decir:
int total = rowObjects.length;
for( int i=0; i<total; i++) {
Saludos y espero haberte ayudado.
El gran problema desde mi punto de vista es la falta de soporte para los indices, es decir los archivos CDX, NTX, etc.
Gracias por la traduccion al castellano
Existe una manera de crear programaticamente un archivo Indice .NDX ?
Con esta librería hasta donde se no se puede pero podrías probar con el siguiente link que te puede orientar un poco mas sobre eso.
Es una libreria llamada xBaseJ que supuestamente te permite trabajar con archivos ndx y mdx pero no lo he probado.
http://sourceforge.net/forum/forum.php?thread_id=2092244&forum_id=766925
Saludos y espero te sirva la info.
expectacular que tengas esta informacion, quiero empezar con llava y todos mis sistemas estan en xbase, intentare e intentare
Hola como estas, soy principiante en java y estaba viendo como crear dbf en java, estoy probando el codigo q sale en esta pagina y me sale un error,
Exception in thread «main» java.lang.ArrayIndexOutOfBoundsException: 3
at prueba.PruebaBbf.main(PruebaBbf.java:56)
como si el arreglo tuviera las dimensiones equivocadas, que podre estar haciendo mal??
Me sale el mismo error que podrá ser?
Hola Jesus:
Puedes utilizarlo tal cual esta en este ejemplo o en su defecto tomar el ejemplo que esta en la pagina en ingles y compilalo ten en cuenta que debes tener la libreria cargada en tu classpath ademas luego de que lo compiles anda anadiendo mas codigo de acuerdo a tu necesidad.
Lo he probado muchas veces y como ves otras personas que han leido este post tambien y no han tenido ningun problema te invito a que lo compiles tal cual esta el ejemplo aqui y sino mismo te funciona yo te devuelvo el correo para que me envies tu codigo y revisarlo.
Saludos.
Hola DaRWin,
Gracias por tu respuesta, y justo estaba programando lo que necesitaba, y logre hacer lo q tenia propuesto, es pasar de una Base de datos oracle a dbf con el programa que estoy elaborando, pero tengo unas dudas, cuando intento abrir un dbf con el visual foxPro 9.0 me sale un error «Table ‘c:\xxx.dbf’ has become corrupted, the table will need to be repaired», por lo q busque en los foros y al parecer es un problema de version, mi pregunta seria como puedo hacer para no tener ese problema.
Mi otro problema que cuando creo el dbf y los campos numericos se muestran de esta manera ,00 7,36 pero desearia q salga asi 0.00 7.36, como podria hacerlo???
Muchas Gracias de antemano 😀
Hola DaRWin:
Muchisimas gracias por la ayuda de la libreria pero me a surgido un problema cuando deseo agregar registros con Sync Mode y no me funciona y no tengo ni idea me podrias explicar un poco mas o enviar un ejemplo para poderlo entender un poco mejor
de antemano Gracias
Mmmmm, no me gustó mucho. Prefiero otra. Entren aquí y verán a que me refiero. Es mucho más «estándar», permite el uso de consultas SQL.
http://3d2f.com/programs/46-008-stelsdbf-fast-dbf-jdbc-driver-dbase-xbase-foxpro-download.shtml
Seguro que un odbc es mejor, pero no es gratis…
Que diferencia puede haber entre un archivo dbf de VisualFoxPro y uno de dBase IV?
alescribirlos en dbf los double los manda con una coma separador de decimales peroen el archivo que necesito los requierocon punto decimal y no coma asi q si ayudan en eso gracias
Para agregar rows en un DBF que ya existe «archivo.DBF» que tengo que hacer??
Yo de nuevo. Tambien me gustaría ver en el ejemplo que se agreguen Date.
hola! tenes un ejemplo de como guardar un dato logico?? gracias!
Al parecer no soporta campos memo , conocen alguna libreria que este completa soporte full dbase IV ?
100000000000 de gracias por tu trabajo de traducir. La verdad que no se porque los trabajos de traducción nunca son bien valorados.
Es justo lo que buscaba. Ahora (abuso de tu gentileza) ando buscando la manera más simple de sacar un array (en realidad es la base de datos, o parte de su contenido) en una ventana.
Gracias mil.-
Excelente trabajo .. Gracias doy por personas como tu que se dan el tiempo de aportar a los demas.
Muchas gracias, esto me cayo a pedir de boca hace un tiempo…
se podra hacer una tipo consulta osea de los 500 registros que tiene el archivo DBF seleccionar solo los que tengan id > 20 por ejemplo???? se puede hacer eso?’
Imagino que sip pero te tocaría hacer un trabajo extra de comparar los datos cuando aun son cadena, es lo que se me ocurre en este momento.
Saludos.
Hola, como trabajo en la facultad debo realizar un programa web que interactue con una base de datos Fox (extension .DBC, y tablas .DBF), queria saber si este mini tutorial sirve para varias tablas o es mucho lio relacionar tavlas por separado y seria mejor copnectar toda lka base de datos que es :DBC, en este caso como lo harian?
gracias y por favor necesito respuestas, si malgguno q sabe me escribe a mi mail muy agradecido
martinr84@gmail.com
Hola amigo cuando exporte me sale coma en vez de punto sabes la solucion
купить коммуникатор харьков
Por favor da mas detalles acerca de las comas, imagino que te refieres a las comas en lugar de los puntos en los números, si es asi creo que deberias trabajar los datos antes de escribirlos. es decir con algo asi como sustituir estas comas con puntos con alguna funcion sobre los strings.
Saludos.
Hola, estoy programando algo con archivos DBF pero tengo un problema, cuando leo de un archivo DBF caracteres ñ , ª o cualquiera de esos no me los toma y me los cambia por simbolos raros, ¿como puedo hacer para que lo que lea lo haga en formato iso-8859? ..
Saludos
yo tambien tuve el problema de la coma(,) y el punto(.), asi que hice unas pequeñas modificaciones a la libreria para poder trabajar con la variable Locale, la cual es la que define si escribe la , o .
esta en mi blog: http://jchancafe.posterous.com/javadbf-seteado-locale
saludos.
alguien me puede ayudar, mi problema es el siguiente:
tengo un archivo bdf con mas de 9 millones de registros y con esta libreria solo puedo leer poco mas de 500,000 registros.
lo que pretendo hacer con eso es un migrador, que paso todos estos dato hacia oracle. En este archivo se almacenan el maestro detalle de unas facturas y ps tiene cambios diarios.
me gustari que me dieran alguna recomendacion y si es podible solucionar esto.
De ante mani muchas gracias.
Se que es post es un poco antiguo, pero me marca el siguiente error
Invalid record. Invalid number of fields in row
Estoy tratando de agregar 33 campos, tendra algo q ver eso?
Hola, como debo de hacer si quiero leelo por filas?
Hola, soy nuevo x aqui y tengo una pregunta. ¿por que me pone una coma en vez de un punto cuando guardo un decimal? es decir me deberia guardar 6400.00 y no 6400,00. Ademas cuando intento leerlo me saca Failed to parse Number: For input string: «6400,00».
Agradezco las respuestas.
hola buenos dias!
Lo que pasa es que debo de escribor en una base de datos que ya esta hecha, me podrian decir como realizr este proceso?
Hola, mi consulta es la siguiente, como puedo leer los campos «NULL» o nulos y vacios con esta herramienta?
Hola, gracias por tu ayuda! esta muy buena la información!
Estoy haciendo una aplicación que crea un tabla dbf y uno de los campos es de tipo fecha (Date), pero cuando tengo que especificar el tamaño me sale error, por ejemplo:
DBFField fields[] = new DBFField[ 3];
fields[0] = new DBFField();
fields[0].setName( “id_tabla”);
fields[0].setDataType( DBFField.FIELD_TYPE_N);
fields[0].setFieldLength( 4);
fields[1] = new DBFField();
fields[1].setName( “longitud”);
fields[1].setDataType( DBFField.FIELD_TYPE_N);
fields[1].setFieldLength( 4); /*********
fields[1].setDecimalCount( 2); //******
fields[2] = new DBFField();
fields[2].setName( “fecha”);
fields[2].setDataType( DBFField.FIELD_TYPE_D);
fields[2].setFieldLength( 10); // aqui es donde me sale el error.
//… siguel el codigo
Mi pregunta es: con que tamaño se define una fecha (MM/dd/yyyy)? donde me da error.
Tambien me pasa que cuando asigno los valores Double al cambo 1 (longitud – marcardo como /*******) no me los copia correctamente porque los valores que copio tienen longitudes diferentes, por ejemplo: 125.2 – 23.56; estos se derias guardar en dos registros, en efecto se crean los dos registros pero no se copian los valores, es decir, el campo queda en cero.
Podrian ayudarme? Muchas gracias!
Saludos!
Hola muy bueno gracias, queria saber una cosa, donde puedo encontrar la documetacion para saber las funciones de la libreria javadbf? gracias
Hola a todos.
Tengo problemas al agregar registros numericos intercambia los puntos y comas. He visto un articulo en el que comentan cambiar el Locale. ¿Sirve también para archivos no nuevos?
Un saludo
Hola alguien pudo solucionar el problema de la fecha? quiero grabarla y me da error
Buen día,
En la empresa manejamos visual fox pro7 y quiero que una tabla de la base de datos que allí se maneja .dbf (producto.dbf) pueda visualizarla en una aplicación hecha en Java para comparar un campo de allí, por ejemplo código con otra base de datos en este caso Sqlite que ya lo tenía en la aplicación hecha en java.
Solamente con poder leer la tabla de Vfp7 me serviría mucho.
Agradezco su valiosa ayuda.
Buenas;
primeramente gracias por ofrecer la traduccion que es lo que me permitio llegar fasilmente a este post,,
soy nuevo en java se me hacia nesesario obtener esta libreria la cual probe y me facilita mucho,, pero tengo una duda cuanto quisiera por ejemplo obtener datos de mysql server (es con la que trabajo) y escribir un documento .dbf como lo realizaria de manera sencilla como “Sync Mode” pero no comprendo bien como se maneja si alguien tubiera algun ejemplo por favor me podrian mandar a mi correo
buenas como hago para hacer un if(estatus = 0) donde el “estatus=0″ son de la base de datos y no atributos ni variables de java trabajo con mySQL en NetBeans muchas gracias
Buenas noches no se si aun esten comentando mi problema es este… estoi intentando leer un archivo de VFP y solo me lee unos datos lanzandome el error: Failed to parse Number: For input string: «PROY»
Como puedo slucionarlo.. soi principiante jeje
el archivo ke intento leer es de visual fox pro en .DBF, ya pudimos acceder alos datos de otras tablas pero en una de ellas nos lanza el error que mencione anteriormente..
Alguien sabe como puedo grabar archivos dbf’s vacios? o sea solo con la estructura sin llenarlo de datos.
Buenos días,
Gracias por el tutorial, esta muy completo, pero tengo una pregunta, como puedo hacer para actualizar un registro con javaBDF.
Disculpen ¿saben si existe una libreria para hacer lo mismo con C# desde Visual Studio?
Hola Buenas tardes, hay manera de actualizar los registros del DBF porque hasta ahora no he encontrado algo similar en el proyecto.
Saludos
Hola buenas tardes, disculpa para sobrescribir un archivo DBF ya creado, como se pudiera realizar?
Como nota el archivo contiene 138 campos y mas de 1000 registros