dbf文件生成后,最后一列的_nullflags是干嘛的??

堆代码的爱因斯坦 2016-01-07 09:42:45
可以去掉吗?
...全文
551 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
xuzuning 2016-01-10
  • 打赏
  • 举报
回复
你要的是 dBASE 3 或 FoxPro 2.5 的 dbf 格式 只能编程直接写文件了,这么低版本的驱动应该很难找到了
  • 打赏
  • 举报
回复
我换了一种方式 string outconnstring = string.Format("Provider = Microsoft.Jet.OLEDB.4.0;Data Source ={0};Extended Properties=dBASE IV;User ID=;Password=;", filename); OleDbConnection outConn = new OleDbConnection(outconnstring);////VFPOLEDB OleDbCommand dc = outConn.CreateCommand(); outConn.Open(); 但是报错 找不到可安装的 ISAM。
  • 打赏
  • 举报
回复
引用 10 楼 xuzuning 的回复:
嗯,测试了一下:只有在 vfp 中建的表才会没有(不选 NULL 项)
对的,只要程序建表语句不写 not null ,就会有的,蛋疼!!
xuzuning 2016-01-10
  • 打赏
  • 举报
回复
不好意思,我是才学的 C#,光看代码还反应不过来 假定有 2 个字段:A C(8)、B N(10) 内容分别为 a、123 则 记录数据 = string.Format(" {0,-8}{1,10}", "a", 123); 将得到的字符串写入文件就可以了
  • 打赏
  • 举报
回复
16#就是我写入数据的,其中有个字符串转字节的方法如下:
  public static byte[] ConvertStringToBytes(string tempStr, int limitLength)
        {
            byte[] result = null;
            byte[] tempBytes = UTF8Encoding.GetEncoding("gb2312").GetBytes(tempStr.Trim());//gb2312
            if (tempBytes.Length == limitLength)
            {
                result = tempBytes;
            }
            else if (tempBytes.Length > limitLength)
            {
                for (int i = 0; i < limitLength; i++)
                {
                    result[i] = tempBytes[i];
                }
            }
            else if (tempBytes.Length < limitLength)
            {
                result = new byte[limitLength];
                for (int i = 0; i < tempBytes.Length; i++)
                {
                    result[i] = tempBytes[i];
                }
            } return result;
        }
  • 打赏
  • 举报
回复
引用 21 楼 xuzuning 的回复:
sjnf 字段宽为 8 你是怎么充填数据的? 不足 8 字节的部分要补空格而不是 \0
可否加QQ细聊?
xuzuning 2016-01-10
  • 打赏
  • 举报
回复
sjnf 字段宽为 8 你是怎么充填数据的? 不足 8 字节的部分要补空格而不是 \0
  • 打赏
  • 举报
回复
而采用如上你说自己写dbf文件方式解析工具查看如下
可是上传到他们平台会报
提示一个字段不能为null,很明显是定义时要标识not null,但是如上方式又该如何定义字段类型呢??
  • 打赏
  • 举报
回复
引用 18 楼 xuzuning 的回复:
其实你可以像他们要一个 dbf 文件,解析一下

可以正常上传的
我采用VFPOLEDB方式代码生成的
xuzuning 2016-01-10
  • 打赏
  • 举报
回复
其实你可以像他们要一个 dbf 文件,解析一下
xuzuning 2016-01-10
  • 打赏
  • 举报
回复
那你的对方使用的是 dbase iv 或以上吧 dbase iii 是没有主键的,vfp 也是没有的
  • 打赏
  • 举报
回复
这个方式其实我已经试过了,是采用如下代码,但是此种dbf文件,使用vfp是可以打开,但是人家平台说主键不能为空之类的,我怀疑此类方式,是不是不会被认为是正规的数据结构表呢?
/// <summary>                                                                        
        /// 保存DBF文件                                                                    
        /// </summary>                                                                      
        /// <param name="filepath">DBF文件保存路径</param>                               
        /// <param name="dataGridView">表格对象</param>                                     
        private void WriteDBFFile(string filepath, DataGridView dataGridView)
        {
            try
            {
                int rowCount = dataGridView.RowCount;
                int columnCount = dataGridView.ColumnCount;
                if (rowCount > 0 && columnCount > 0)
                {
                    FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.Write);
                    BinaryWriter bw = new BinaryWriter(fs);
                    byte tempByte;
                    byte[] tempBytes;
                    int i, j, tempInt; int[] fieldLength = new int[columnCount];
                    int tempMax = 0;
                    for (i = 0; i < columnCount; i++)
                    {
                        tempMax = 0;
                        for (j = 0; j < rowCount; j++)
                        {
                            //if (dataGridView[i, j].Value != null && dataGridView[i, j].Value.ToString() != "")
                            if (dataGridView[i, j].Value != null )
                            {
                                if (dataGridView[i, j].Value.ToString().Length > tempMax)
                                {
                                    tempMax = dataGridView[i, j].Value.ToString().Length;
                                }
                            }
                        }
                        fieldLength[i] = tempMax * 2;
                        //ywk 处理空值情况下写入列名2016年1月6日 11:27:30
                        if (fieldLength[i] == 0)
                        {
                            fieldLength[i] = 10;
                        }
                    }
                    //写入文件头   
                    {
                        //第0个字节为数据库类型 
                        tempByte = 0x03;
                        bw.Write(tempByte); tempBytes = new byte[3];
                        //第1个字节为保存时的年份-1990                                      
                        tempInt = DateTime.Now.Year - 1900;
                        tempBytes[0] = System.Convert.ToByte(tempInt);
                        //第2个字节为保存时的月份  
                        tempBytes[1] = System.Convert.ToByte(DateTime.Now.Month);
                        //第3个字节为保存时的日 
                        tempBytes[2] = (byte)(DateTime.Now.Day);
                        bw.Write(tempBytes);
                        //第4-7个字节为行数
                        bw.Write(rowCount);   //第8-9字节为文件头的长度 
                        tempInt = 33 + columnCount * 32;
                        bw.Write((Int16)tempInt);      //第10-11为每行数据所占长度 
                        tempInt = 1;
                        for (i = 0; i < columnCount; i++)
                        {
                            tempInt += fieldLength[i];
                        }
                        bw.Write((Int16)tempInt);     //第12-31为保留字段,默认为0 
                        tempBytes = new byte[20];
                        bw.Write(tempBytes); string tempColumnName;
                        //开始写字段  
                        for (i = 0; i < columnCount; i++)
                        {
                            tempColumnName = dataGridView.Columns[i].Name;
                            tempBytes = ConvertStringToBytes(tempColumnName, 11);
                            bw.Write(tempBytes);
                            //第11个字节为数据类型 
                            tempByte = (byte)('C');//数据类型为字符串
                            bw.Write(tempByte);
                            //第12-15为保留字节   
                            tempBytes = new byte[4];
                            bw.Write(tempBytes);
                            //第16个字节为字段长度  
                            tempByte = (byte)fieldLength[i];

                            bw.Write(tempByte);
                            //接着第17-31都为保留字节 
                            tempBytes = new byte[15];
                            bw.Write(tempBytes);
                        }
                        //最后以0D结尾 
                        tempByte = 0x0D;
                        bw.Write(tempByte);
                    } object tempValue;
                    //写入单元格数据
                    for (i = 0; i < rowCount; i++)
                    {
                        //每一行第一个字节默认为20  
                        tempByte = 0x20;
                        bw.Write(tempByte);
                        for (j = 0; j < columnCount; j++)
                        {
                            tempValue = dataGridView[j, i].Value;
                            if (tempValue != null)
                            {
                                tempBytes = ConvertStringToBytes(tempValue.ToString(), fieldLength[j]);
                                //byte cut = 0x20;//0x00;
                                //tempBytes = byteCut(tempBytes);
                                bw.Write(tempBytes);
                            }
                            else
                            {
                                tempBytes = ConvertStringToBytes("", fieldLength[j]);
                                bw.Write(tempBytes);
                            }
                        }
                    } bw.Close();
                    fs.Close();
                }
                else
                {
                    MessageBox.Show("表格中没有数据", "提示!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            catch (Exception except)
            {
                MessageBox.Show(except.Message, "提示!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
xuzuning 2016-01-10
  • 打赏
  • 举报
回复
自己写也是不困难的
表头记录的结构
字节偏移 说明 
0 文件类型
0x02FoxBASE
0x03FoxBASE+/dBASE III PLUS,无备注
0x30Visual FoxPro
0x43dBASE IV SQL 表文件,无备注
0x63dBASE IV SQL 系统文件,无备注
0x83FoxBASE+/dBASE III PLUS,有备注
0x8BdBASE IV 有备注
0xCBdBASE IV SQL 表文件,有备注
0xF5FoxPro 2.x(或更早版本)有备注
0xFBFoxBASE 
1 – 3 最近一次更新的时间(YYMMDD) 
4 – 7 文件中的记录数目 
8 – 9 第一个数据记录的位置 
10 – 11 每个数据记录的长度(包括删除标记) 
12 – 27 保留 
28 表的标记
0x01具有 .cdx 结构的文件
0x02文件包含备注。
0x04文件是数据库(.dbc)
请注意,这个字节可以包含任何上面值的和。例如,0x03 表明表具有结构化 .cdx 和一个备注字段。 
29 代码页标记 
30 – 31 保留,包含 0x00 
32 – n 字段子记录
字段的数目决定了字段子记录的数目。表中每个字段都对应一个字段子记录。 
n+1 头记录终止符(0x0D) 
n+2 到 n+264 此范围内的 263 个字节包含后链信息(相关数据库 (.dbc) 的相对路径)。如果第一个字节为 0x00,则该文件不与数据库关联。因此数据库文件本身总是包含 0x00。 


1 头记录中的第 8 到第 9 个字节指示数据文件中数据的起始位置。数据记录从删除标记字节开始。如果此字节为 ASCII 空格 (0x20),该记录没有删除标记,如果第一字节为星号 (0x2A),该记录有删除标记。在标记之后是字段记录中所命名各字段中的数据。

字段子记录结构
字节偏移 说明 
0 - 10 字段名(最多 10 个字符 —若少于 10 则用空字符 (0x00) 填充) 
11 字段类型
C–字符型
Y–货币型
N–数值型
F–浮点型
D–日期型
T–日期时间型
B–双精度型
I–整型
L–逻辑型
M–备注型
G–通用型
C–字符型(二进制)
M–备注型(二进制)
P–图片型 
12 - 15 记录中该字段的偏移量 
16 字段长度(以字节为单位) 
17 小数位数 
18 字段标记
0x01系统列(用户不可见)
0x02可存储 null 值的列
0x04二进制列(只适于字符型和备注型) 
19 – 32 保留 


有关对每个记录中字符的限制以及字段数目的最大值等详细内容,请参阅“Visual FoxPro 系统容量”。

说明
除非在文件中添加下列功能,否则 Visual FoxPro 将不修改按 FoxPro 2.x 文件格式保存的文件标头: 

支持 null 值


日期时间型、货币型及双精度型数据


字符字段和备注字段标记为二进制


在数据库 (.dbc) 文件中添加表 
提示 可以使用下面的公式求出表文件中字段的数目:(x – 296/32) 公式中,x 表示第一个记录的位置(表头记录的第 8 到第 9 个字节),296 表示 263(后链信息)+ 1(头记录终止符)+ 32(第一个字段子记录),32 是字段子记录的长度。
删除标记 1 字节,在每条记录的前面 只要没有备注字段,基本没有困难
  • 打赏
  • 举报
回复
引用 13 楼 xuzuning 的回复:
你要的是 dBASE 3 或 FoxPro 2.5 的 dbf 格式 只能编程直接写文件了,这么低版本的驱动应该很难找到了
完蛋了!!那无法实现了哦,人家平台要的就是dbase的
xuzuning 2016-01-09
  • 打赏
  • 举报
回复
你在建表指令中不出现 NULL 字样就不会有 _NullFlags 列
  • 打赏
  • 举报
回复
引用 5 楼 xuzuning 的回复:
_NullFlags 列是用于记录允许为 NULL 的列在该行是否为 NULL 其字段类型为 0(零)使用时不应作为正常字段处理
我想把他去掉,因为现在有个平台需要上传我的dbf,人家的可以,我的不可以,我能发现唯一的不同就是人家没有这个列, 你们Datatable导出为dbf都是如何做的!我用了N种方式,dbf浏览器都可以正常浏览,但第三方平台搞死认不出我生成的文件!!!
xuzuning 2016-01-09
  • 打赏
  • 举报
回复
嗯,测试了一下:只有在 vfp 中建的表才会没有(不选 NULL 项)
qq_33669630 2016-01-09
  • 打赏
  • 举报
回复
用嘛玩意生成的dbf文件?
  • 打赏
  • 举报
回复
引用 7 楼 xuzuning 的回复:
你在建表指令中不出现 NULL 字样就不会有 _NullFlags 列
我现在就没写啊。。可是生成的DBF里面却有! 建表语句如下: create table N041_njcgyy(SJNF C(4) ,XZQH C(6) ,JGDM C(9) ,S0101 C(1) ,S0102 C(2) ,S0103 C(15) ,S0104 C(1) ,S0105 N(20) ,S0106 C(1) ,S0107 C(2) ,S0201 C(8) ,S0202 C(4) ,S0301 C(8) ,S0302 C(4) ,S0401 C(1) ,S0402 C(10) ,S0403 C(8) ,S0501 C(10) ,S050101 C(1) ,S0502 C(10) ,S050201 C(1) ,S0503 C(10) ,S050301 C(1) ,S0504 C(10) ,S0505 C(10) ,N0601 N(10) ,N060101 N(20) ,N060102 N(20) ,N060103 N(20) ,N060104 N(20) ,N060105 N(20) ,N060106 N(20) ,N060107 N(20) ,N060108 N(20) ,N060109 N(20) ,N0701 N(20) ,N070201 N(20) ,N070202 N(20) ,N070203 N(20) ,N070204 N(20) ,N070205 N(20) ,NM1 C(20) ,NM2 C(20) ,NM3 C(20) ,NM4 C(20) ,NM5 C(20) ,JGMC C(80) )
iAaronHua 2016-01-07
  • 打赏
  • 举报
回复
贴下代码吧,就这么说真不知道你是什么情况
加载更多回复(4)

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧