`
linwei_211
  • 浏览: 192198 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

      最近在做项目的时候,发现有一个导出数据成DBF文件的功能的异常。导出的DBF文件用VFP或者打开,发现数据错位的现象,本该属于前一列的数据跑到后面那一列去了,这是问题一。还有一个问题,有的数据导出去以后出现了乱码,而且数据错位很严重,根本没有一条数据可以看的。而且tomcat是不报任何错误的。
      之前没整过读写DBF文件这类的东西,也不太明白这个到底是什么原因,跟了一下代码,发现写进去的数据没有乱啊,而且编码设置的GBK,写中文也不会乱码啊,都很正常。纠结了很长时间,从网上找了很多读写DBF的例子,跟我项目的也大相径庭,于是又将javadbf-0[1].4.0.jar这个里面的各个类反编译了,研究了一番,也没发现什么蛛丝蚂迹对我有帮助..............
  然后我发现导出的DBF文件是从某一列以后开始产生数据错位的,该DBF总共有5列:目录号、文件号、题名、总页数、负责人。本该属于题名的列数据全都跑到总页数里面去了,后面的各列数据也都往后偏移一列。于是查看了导出的DBF文件的表结构,居然意外的发现题名那一列的宽度是0,检查代码,在代码里写进去的列宽度分别是20、30、512、30、20,因为考虑到题名字段的内容比较多,所以故意将其长度设的比较大,可是不明白为什么他会变成0呢,看了DBFField.java的setFieldLength方法,如果传进去的时候就是0的话,他应该会打印Field length should be a positive number这一句话的,
 
public void setFieldLength(int value)
  {
    if (value <= 0)
    {
      throw new IllegalArgumentException("Field length should be a positive number");
    }

    if (this.dataType == 68)
    {
      throw new UnsupportedOperationException("Cannot do this on a Date field");
    }

    this.fieldLength = value;
  }

没有打印,而且我这里是setFieldLength(titleLength),titleLength的值是动态传入的,打断点看到的是512,可确实是到了DBF文件里,题名的列宽度就变成了0,为什么呢?
      于是写了1024,导出的DBF题名一列还是0,写了2048,也变成了0,于是以为凡是这个长度能整除1024,或者1024能整除这个数,就会在DBF文件里变成0,又多试了几次,写了个513,导出的DBF里宽度是1,而且中文全是乱码,写514,导出的DBF里宽度是2,写256,导出的DBF里宽度是0,写257, 导出的DBF里宽度是1,后来反复研究发现,DBF文件里的宽度取的是setFieldLength(titleLength)里面传进去的titleLength%256的值,因为1024%256==0;2048%256==0;256%256==0;513%126==1;257%256==1;514%256==2,也就是说你在setFieldLength写256和512是相同的结果。
      于是心想应该是javadbf本身的问题,想试图修复这个问题,但是在javadbf的各个类里没有找到任何可能导致此问题的痕迹,因为在各个类里根本没有找到255这个数字。最后想着只能是在自己的代码里去避免这个问题了,那可是如果我题名那一列确实数据比较多我就要给他写列宽为512咋办,心想可不可以手动的在VFP里建一个文件将其宽度设为512呢,于是一试才发现,通过VFP里面的工具向导---表向导建表的时候,通过它自己增加和减小按钮列宽度增大254,再点向上按钮,增大就没变化买反映了,手动的在宽度框里输了个255,右上角立刻提示范围:1-254。于是差不多清晰了,应该是DBF文件里宽度最大允许设置到254,但是我可以通过代码写入255,这应该是极限了,所以传过去的大于256的数字就解析成了对256取余的结果了。
      于是我只能是去在往DBF文件写数据的代码里去避免了,我是这样处理的,将设置宽度的代码修改为:
      
 if(titleLength>=256){
             fields[i].setFieldLength(255);                
      }else{
            fields[i].setFieldLength(titleLength);
      }
       将写值的地方修改为
             if(ob.toString().length()>=256){
                   if(ob.toString().matches("^[\u4e00-\u9fa5]{0,}$")&&ob.toString().length()>=127){//如果是中文,就只要前127个字
                          rowData[j] = ob==null?"":ob.toString().substring(0,127);
                 }else{
                    rowData[j] = ob==null?"":ob.toString().substring(0,255);
                 }
            }else{
                    rowData[j] = ob==null?"":ob.toString();
            }
       然后就OK了,算是解决了。
       随手写了个test.java,如下:
package cn.welcome.test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import com.linuxense.javadbf.DBFBase;
import com.linuxense.javadbf.DBFField;
import com.linuxense.javadbf.DBFReader;
import com.linuxense.javadbf.DBFWriter;

public class test {
 private static FileInputStream inputStream;
 private static DBFReader reader;       //读取dbf文件对象
 private static int numberOfFields;
 private static int numberofRecord;

 public static void main(String args[]) throws IOException{
  DBFField fields[] = new DBFField[3];

     fields[0] = new DBFField();
     fields[0].setName("姓名");
     fields[0].setDataType( DBFField.FIELD_TYPE_C);
     fields[0].setFieldLength(10);

     fields[1] = new DBFField();
     fields[1].setName("年龄");
     fields[1].setDataType( DBFField.FIELD_TYPE_N);
     fields[1].setFieldLength(768);

//     fields[2] = new DBFField();
//     fields[2].setName("性别");
//     fields[2].setDataType( DBFField.FIELD_TYPE_N);
//     fields[2].setFieldLength(12);
//     fields[2].setDecimalCount(2);
     fields[2] = new DBFField();
     fields[2].setName("性别");
     fields[2].setDataType( DBFField.FIELD_TYPE_C);
     fields[2].setFieldLength(12);

     DBFWriter writer = new DBFWriter();
     writer.setFields(fields);

     Object rowData[] = new Object[3];
     rowData[0] = "1000";
     rowData[1] = "John";
     rowData[2] = "111";

     writer.addRecord(rowData);

     rowData = new Object[3];
     rowData[0] = "1001";
     rowData[1] = "检查数据检查数据检查数据检查数据检查过后就会恢复的";
     rowData[2] = "222";
     writer.setCharactersetName("GBK");
     writer.addRecord(rowData);

     rowData = new Object[3];
     rowData[0] = "1002";
     rowData[1] = "Rohit";
     rowData[2] = "333";

     writer.addRecord(rowData);
    
     writer.write(new FileOutputStream("D:\\creatDBF.dbf"));
  inputStream = new FileInputStream("D:\\creatDBF.dbf");
  reader = new DBFReader(inputStream);
  reader.setCharactersetName("GBK");
  numberOfFields = reader.getFieldCount();
  numberofRecord = reader.getRecordCount();
 
  for(int i = 0;i < reader.getFieldCount(); i++){
   DBFField dbf = reader.getField(i);
//   System.out.println(dbf.getName());
  }
  Object[] rowValue;
  while((rowValue = reader.nextRecord())!=null){
   for(int i = 0 ; i < rowValue.length ; i++){
//    System.out.println(rowValue[i]);
   }
  }
 }
}
如上fields[1].setFieldLength(768);打开D盘根目录下的creatDBF.dbf文件发现年龄一列宽度是0,
写成257,或者259,creatDBF.dbf里面的数据都出现乱码,写258,发现第二列数据出现错位,而且第三列数据丢失。写成255就好了,没有问题了。
 

分享到:
评论
2 楼 WH_LPWH 2015-09-30  
     哥呀 牛逼 大赞一个
1 楼 mengqingyu 2012-05-14  
遇到同样的问题,受教了!

相关推荐

    解决了DBF数据和表头乱码的javadbf.jar

    在IT行业中,数据库文件格式多样,DBF(dBase File)就是其中一种常见的表格数据存储格式,尤其在老式的应用程序和数据迁移中常见。DBF文件由一系列记录组成,每条记录包含多个字段,每个字段都有自己的名称和类型。...

    使用Java实现对dbf文件的简单读写

    使用 Java 实现对 dbf 文件的简单读写 Java 是一种广泛使用的编程语言...使用 Java 实现对 dbf 文件的简单读写需要遵循一定的步骤和类的使用。通过上述代码实现,可以实现对 dbf 文件的读写操作,满足实际应用的需求。

    解决ArcMap Desktop 10.1-10.6 导出dbf出现乱码.rar

    在GIS领域,ArcMap Desktop是一款广泛使用的地理信息系统软件,用于数据可视化、地图制作以及空间分析。...通过正确的方法和工具,可以确保在处理中文数据时不会出现乱码,从而提高工作效率和数据质量。

    javadbf中文乱码

    在处理DBF(dBASE文件)格式的数据时,可能会遇到中文乱码问题,尤其是在使用Java进行操作时。`javadbf`是一个Java库,专门设计用于读取和写入DBF文件,它提供了处理此类问题的解决方案。在本文中,我们将深入探讨...

    java读取DBF解决方案(可以解决javadbf.jar对DBF部分中文乱码和错行等杂症)

    X86server,进入 控制面板--系统和安全--管理工具--ODBC数据源--右键管理员方式运行 X64(win7,server):C:\windows\sysWow64\odbcad32.exe 右键管理员方式运行,如图1 在"系统DSN"中找到刚安装驱动后增加的项...

    javadbf 标题中文乱码处理

    基于javadbf-0.4.0而修改的,导入dbf文件时标题转码采用系统默认编码处改为采用用户自定义的转码格式,从而解决标题乱码的问题

    excel xlsx文件读取 javadbf乱码解决

    该项目包含了项目所需要的jar包以及测试案例。项目使用环境为eclipse jdk1.8 1.poi.Testpoi为测试用例;...3.解决了javadbf读取dbf文件表头和数据乱码问题,com.webadmin.util.dbf.DBFReaderTest为测试用例。

    java快速导出几十万百万生成DBF文件数据后台内附有javadbf.jar

    本文将深入探讨如何使用Java来快速导出大量数据到DBF文件,以及如何利用`javadbf.jar`库进行高效操作。 首先,DBF文件是基于dBase III、IV或FoxPro等早期数据库管理系统的文件格式。它以ASCII文本存储表格数据,...

    javadbf 标题内容中文乱码解决

    基于javadbf-0.4.0修改而来,a.修改了基类中的默认字符编码;b.修改了写入类中的字节填充位置计算方法,使之支持双字节; 补充:通常dbf使用excel打开时,gb2312的中文能正常显示,utf8的不行,所以默认字符集设置成...

    java 读写 DBF 文件 xBaseJ

    在IT行业中,数据库文件格式是数据存储和交换的重要方式之一,DBF(dBase File Format)就是其中一种常见的表格数据格式,尤其在早期的桌面数据库系统中广泛应用。本篇文章将详细探讨如何使用Java来读写DBF文件,...

    dbf解决中文乱码

    5. **元数据检查**:DBF文件的头信息包含了编码信息,有时这些信息可能不正确,导致乱码。可以手动编辑DBF文件的元数据,修正字符集信息。 6. **手动处理**:如果文件较小,可以考虑手动用文本编辑器(如Notepad++...

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

    DBF文件通常包含一个表的结构信息和数据记录,每条记录由多个字段组成,每个字段有自己的数据类型,如字符、数字、日期等。文件头包含了字段信息,包括字段名、数据类型、长度和位置等。JavaDBF库正是利用这些信息来...

    java 写dbf文件

    打包文件路径 : dbf4j\artifacts\dbf4j_jar java -jar dbf4j.jar test.xml 20190416 test.xml 是配置文件,20190416是日期参数

    Javadbf时解决DBF中文写入乱码问题javadbf-0.4.0.jar

    使用Javadbf时解决DBF中文写入乱码问题,用此javadbf-0.4.0.jar代替官方原jar文件即可解决

    javadbf.jar修正数据和表头的乱码问题

    javadbf的jar包,现有的所谓修正包只是修正了数据的乱码,表头还会乱码。 本jar包修正了数据和表头的乱码。 注意!使用方法与原来有不同,如果指定编码,请使用以下构造方法: new DBFWriter(File dbfFile, String ...

    dbf-jdbc-wisecoders,JAVA 读写DBF文件工具包

    1. **JDBC接口**:`dbf-jdbc-wisecoders`通过提供一个类似于JDBC(Java Database Connectivity)的接口,让Java开发者可以使用他们熟悉的SQL查询来访问和操作DBF文件。这大大简化了代码编写,使得DBF文件的处理如同...

    解决arcgis arcmap 10.7导出DBF乱码.reg

    仅针对Arcgis10.7 导出SHP dbf后乱码的解决办法,下载后关闭arcgis,直接双击运行就可。

    DBF.rar_DBF_dbf java_java dbf_读取dbf

    DBF文件主要由文件头、字段定义记录和数据记录三部分组成。文件头包含了文件的基本信息,如记录数量、创建日期等。字段定义记录则定义了每个列的名称、类型和长度。数据记录则存储实际的表格数据。 2. Java读取DBF...

    javadbf.jar-修复中文乱码-部分生僻字显示成问号的问题

    用于在java代码中写入dbf文件并输出文件。在原代码的使用过程中,对于姓名字段中不常见的汉字,会变成“?”号,比如“张芃”,会变成“张?”,这个包是修复这个问题的。

Global site tag (gtag.js) - Google Analytics