使用JAVA写出DBF出现乱码和数据错位

1,用到的jar包:javadbf.jar。

2,如果是小数据量的导出,用普通的方法就可以。

 

用JavaDBF操作(读、写)DBF文件

最近的一个项目需要动态生成DBF文件,用到JavaDBF,简单介绍一下

官方网站:http://javadbf.sarovar.org/

官方英文指南:http://sarovar.org/docman/view.php/32/23/javadbf-tutorial.html

最新版本:<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">0.4.0</st1:chsdate>,最后发布时间还是在<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="1" month="4" year="2004">2004年4月1日</st1:chsdate>,看来DBF真是老了。老归老,有些时候还是得用。

读取DBF文件:

<o:p>

java 代码
  1. public static void readDBF(String path)   
  2.   
  3.     {   
  4.   
  5.        InputStream fis = null;
  6.         try 
  7.         {  
  8.             //读取文件的输入流 
  9.             fis  = new FileInputStream(path);
  10.             //根据输入流初始化一个DBFReader实例,用来读取DBF文件信息
  11.             DBFReader reader = new DBFReader(fis);  
  12.             //调用DBFReader对实例方法得到path文件中字段的个数 
  13.             int fieldsCount = reader.getFieldCount();
  14.             //取出字段信息   
  15.             forint i=0; i<fieldsCount; i++)    
  16.             {   
  17.               DBFField field = reader.getField(i);
  18.               System.out.println(field.getName());
  19.             }   
  20.             Object[] rowValues;   
  21.             //一条条取出path文件中记录   
  22.             while((rowValues = reader.nextRecord()) != null
  23.             {   
  24.               forint i=0; i<rowValues.length; i++) 
  25.               {   
  26.                 System.out.println(rowValues[i]); 
  27.               }   
  28.             }   
  29.           }   
  30.           catch(Exception e)    
  31.           {   
  32.           e.printStackTrace();  
  33.           }  
  34.           finally  
  35.           {   
  36.           try{   
  37.                fis.close(); 
  38.           }catch(Exception e){}  
  39.           } 
  40.     }   

 

写DBF文件:

java 代码

 

  1. public static void writeDBF(String path)   
  2.   
  3.  OutputStream fos = null;
  4.  try  
  5.  {   
  6.      //定义DBF文件字段   
  7.      DBFField[] fields = new DBFField[3]; 
  8.      //分别定义各个字段信息,setFieldName和setName作用相同, 
  9.      //只是setFieldName已经不建议使用   
  10.      fields[0] = new DBFField();   
  11.      //fields[0].setFieldName("emp_code"); 
  12.      fields[0].setName("semp_code");   
  13.      fields[0].setDataType(DBFField.FIELD_TYPE_C);   
  14.      fields[0].setFieldLength(10);   
  15.   
  16.      fields[1] = new DBFField();   
  17.      //fields[1].setFieldName("emp_name"); 
  18.      fields[1].setName("emp_name");   
  19.      fields[1].setDataType(DBFField.FIELD_TYPE_C);   
  20.      fields[1].setFieldLength(20);   
  21.   
  22.      fields[2] = new DBFField();   
  23.      //fields[2].setFieldName("salary"); 
  24.      fields[2].setName("salary");  
  25.      fields[2].setDataType(DBFField.FIELD_TYPE_N);   
  26.      fields[2].setFieldLength(12);   
  27.      fields[2].setDecimalCount(2);   
  28.   
  29.      //DBFWriter writer = new DBFWriter(new File(path));   
  30.   
  31.      //定义DBFWriter实例用来写DBF文件   
  32.      DBFWriter writer = new DBFWriter(); 
  33.      //把字段信息写入DBFWriter实例,即定义表结构  
  34.      writer.setFields(fields);   
  35.      //一条条的写入记录   
  36.      Object[] rowData = new Object[3]; 
  37.      rowData[0] = "1000";   
  38.      rowData[1] = "John";   
  39.      rowData[2] = new Double(5000.00);
  40.      writer.addRecord(rowData);   
  41.   
  42.      rowData = new Object[3];  
  43.      rowData[0] = "1001";  
  44.      rowData[1] = "Lalit"
  45.      rowData[2] = new Double(3400.00);   
  46.      writer.addRecord(rowData);   
  47.   
  48.      rowData = new Object[3];
  49.      rowData[0] = "1002";   
  50.      rowData[1] = "Rohit";  
  51.      rowData[2] = new Double(7350.00);  
  52.      writer.addRecord(rowData);   
  53.   
  54.      //定义输出流,并关联的一个文件   
  55.      fos = new FileOutputStream(path);
  56.      //写入数据   
  57.      writer.write(fos);   
  58.   
  59.      //writer.write();  
  60.  }catch(Exception e)   
  61.  {   
  62.      e.printStackTrace();   
  63.  }   
  64.  finally  
  65.  {   
  66.      try{   
  67.      fos.close();
  68.      }catch(Exception e){}
  69.  }   

注意:writer.addRecord(rowData)时并不真正写入数据,在最后writer.write(fos)时才会把数据写入DBF文件,之前addRecord的数据暂时存放在内存中。如果数据量过大,这种方式显然不适合,内存中存储的数据过多,所以JavaDBF提供了另外一种机制来解决这个问题:Sync Mode(同步模式)。使用方法如下:

用new DBFWriter(new File(path))实例化DBFWriter类,最后写入数据时用writer.write(),这样在每次addRecord时数据就被写入的DBF文件中。

因为初始化DBFWriter时传递了DBF文件,所以不用再定义DBF表结构,如果你定义并加载表结构会报异常。

 

 下面这个函数会根据你传入的数据信息自动生成DBF文件,这样以后我们只要构造好数组,就可以直接得到DBF文件,不用每次都去写重复的代码。

 

 

java 代码
  1. public static void generateDbfFromArray(HttpServletResponse response,
  2. String dbfName, String[] strutName,byte[] strutType,
  3. int[] strutLength, Object[][] data){   
  4.   
  5.    OutputStream fos = null
  6.    try
  7.    {  
  8.        dbfName = new String(dbfName.getBytes("gbk"), "ISO-8859-1");
  9.        response.setContentType("applicationnd.ms-excel");
  10.        response.setHeader("Content-disposition", "attachment; filename=" + dbfName + ".dbf");
  11.        fos = response.getOutputStream();
  12.        int fieldCount = strutName.length;   
  13.        DBFField[] fields = new DBFField[fieldCount]; 
  14.        for(int i=0;i<fieldCount;i++) 
  15.        {   
  16.           fields[i] = new DBFField(); 
  17.           fields[i].setName(strutName[i]); 
  18.           fields[i].setDataType(strutType[i]);  
  19.   //Date类型不能设置字段长度,这里没有处理其它没有字段长度的类型 
  20.   if(strutType[i] != DBFField.FIELD_TYPE_D){ 
  21.            fields[i].setFieldLength(strutLength[i]); 
  22.   }
  23.        }   
  24.   
  25.        DBFWriter writer = new DBFWriter(); 
  26.        writer.setFields(fields);   
  27.        for(int i=0;i<fieldCount;i++) 
  28.        {   
  29.        writer.addRecord(data[i]);
  30.        }
  31.        writer.write(fos);
  32.    }   
  33.    catch(Exception e)  
  34.    {   
  35.        e.printStackTrace();
  36.    }   
  37.    finally  
  38.    {   
  39.        try{  
  40.        fos.close();
  41.        }catch(Exception e){} 
  42.    }   
  43.   
  44. }  

 

可以看到定义JavaDBF表结构或者添加数据时是通过传递数组实现,也就是说只要我们有了这些用来构造表结果和表示结果集的数组就有了DBF文件,那么我们可以通过类似下面这样的函数把ResultSet信息转换成数组信息。

 

Java代码   收藏代码
  1. ResultSet得相关参数代码片断,下面的代码对类型判断和转换还不全面,如果还有其他字段请自行添加  
Java代码   收藏代码
  1. try {  
  2.             ResultSetMetaData meta = rs.getMetaData();  
  3.             int columnCount = meta.getColumnCount();  
  4.             strutName = new String[columnCount];  
  5.             strutType = new byte[columnCount];  
  6.             rs.last();  
  7.             int itemCount = rs.getRow();  
  8.             rs.first();  
  9.             data = new Object[itemCount][columnCount];  
  10.             for (int i = 1; i <= columnCount; i++){  
  11.                 int type = (byte) meta.getColumnType(i);  
  12.                 //2是BigDecimal  
  13.                 if(type == 2){  
  14.                     strutType[i-1] = DBFField.FIELD_TYPE_N;  
  15.                 }  
  16.                 //12是String  
  17.                 else if(type == 12){  
  18.                     strutType[i-1] = DBFField.FIELD_TYPE_C;  
  19.                 }  
  20.                 //91是java.util.Date  
  21.                 else if(type == 91){  
  22.                     strutType[i-1] = DBFField.FIELD_TYPE_D;  
  23.                 }  
  24.                 strutName[i-1] = meta.getColumnName(i);  
  25.             }  
  26.             for (int i = 0; rs.next(); i++){  
  27.                 for (int j = 0; j < columnCount; j++){  
  28.                     Object da = rs.getObject(j+1);  
  29.                     if(da instanceof BigDecimal){  
  30.                         Double d = Double.parseDouble(da.toString());  
  31.                         data[i][j] = d;  
  32.                     }else{  
  33.                         data[i][j] = da;  
  34.                     }  
  35.                 }  
  36.             }  
  37.         }catch (Exception e){  
  38.             e.printStackTrace();  
  39.         }finally{  
  40.             rs = null;  
  41.         }  
 
上面采用的是传统方法进行导出dbf文件,如果大数据量导出时,就要先将文件生成到服务器端,然后从response里拿输入流,将刚生成的文件写到客户端,也就是多一个文件流写入的过程。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页