如何从二进制文件中删除部分字节(使用标准C或C++)(100分)

  • 主题发起人 主题发起人 wfh7710
  • 开始时间 开始时间
W

wfh7710

Unregistered / Unconfirmed
GUEST, unregistred user!
在TC或C++ Builder二进制的读写函数只有fread()、fwrite(),那么如何从文件中删除数据呢?
 
fopen友好几种打开方式,设置一下就可以了。
 
我在做一个有关二进制数据库的问题,我使用fwrite()函数将记录写入文件中,但我现在要实现从文件中删除某条记录(fopen()使用wb+参数)怎么办?
 
首先要找到该条记录,因此应在记录的头尾设好标记。
找到后,可以利用指针或AnsiString字符串操作。
 
我明白你是在定位一个记录,但我现在要从当前位置这一条记录删除,我要的是如何删除对应的字节呀。
谢谢
 
用指针就可以了。
 
你能给我举个例子么? 谢谢
 
char *p1,*p2,*p3;
p1 = "sadfsadfasdfdsfasdfasdfdsfasdf";
p2 = p1;
p2 = p2 + 5;
p3 = p2 + 10;
p2与p3之间是你要删除的。
整理一下字符串就可以了。
 
to 李衍智:
你的实现方法是把所有的文件内容读出来,删除后再写进去?!
有没有什么办法直接在文件里删除??
 
to 陈锡震:
当然可以,不过这么做没必要,如果是内存文件到可以。否则操作是一样的。效率没有提高。
 
怎么做啊?????????????
 
没有办法直接删除。
可以用以下方法解决。
1.把待删除的记录后的每一条记录前移,并截短文件。
2.如果记录没有顺序要求的话,用最后一条记录覆盖待删除的记录,并截短文件。
3.加一个标记,指出记录已删除,在以后的某一个时间(比如关闭文件之前)一次性处理。
 
删除一条记录可获取当前记录位置,并把该位置后的记录逐个向前移动,文件在最后一条记录
停止.
1.获取当前位置currentrec:=stringgrid1.row-1,获取总行数:count:=filesize(DataFile);
2.for i:=currentrec+1 to count-1do
begin
seek(DataFile,i);
read(DataFile,PersonRec);
seek(DataFile,i-1);
write(Datafile,PersonRec);
end;
 
首先我要感谢各位大侠鼎立协助。 我在TC2.0(具体我是在Tornado II开发环境使用C编译器,Tornado II是用来开发实时操作系统VxWork的工具)使用.我想将WinNT下的数据库(*.DB)转换为二进制文件数据库,以便能在VxWorks中使用。
我首先将Paradox数据库文件放到Table1中,再把数据库的信息依次写到文件中。(代码如下:)
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MainUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
int __fastcall TForm1::GetDBFieldNum(void)
{ //获得字段数目
FieldNum=DBGrid1->Columns->Count;
return FieldNum;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::GetRecordNum(void)
{ //获取记录数目
RecordNum=Table1->RecordCount;
return RecordNum;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::GetFieldInf(void)
{ //获取字段的信息(字段名、字段类型、字段长度)
RecordLength=0;
for (int i=0;i<FieldNum;i++)
{
FieName=DBGrid1->Columns->Items->FieldName;
FieType=Table1->Fields->DataType;
FieLength=Table1->Fields->DisplayWidth;
RecordLength=RecordLength+FieLength;
}
return RecordLength;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::WriteFileHead()
{ //写入字段数、记录数、记录长度
fwrite(&amp;FieldNum,sizeof(int),1,fp);
fwrite(&amp;RecordNum,sizeof(int),1,fp);
fwrite(&amp;RecordLength,sizeof(int),1,fp);
for (int i=0;i<FieldNum;i++)
{ //写入字段信息(字段名、字段类型、字段长度)
fwrite(&amp;FieName,80,1,fp);
fwrite(&amp;FieType,20,1,fp);
fwrite(&amp;FieLength,10,1,fp);
}
}
//---------------------------------------------------------------------------
int __fastcall TForm1::ReadFileHead()
{ //读取文件头信息(字段数、记录数、记录长度)和记录的结构信息
rewind(fp);
fread(&amp;FieldNum,sizeof(int),1,fp);
fread(&amp;RecordNum,sizeof(int),1,fp);
fread(&amp;RecordLength,sizeof(int),1,fp);
for (int i=0;i<FieldNum;i++)
{
fread(&amp;FieName1,80,1,fp);
fread(&amp;FieType,20,1,fp);
fread(&amp;FieLength,10,1,fp);
}
SeekNum=ftell(fp);
return SeekNum;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::WriteRecord()
{
AnsiString Record;
AnsiString TmpFie;
Table1->First();
while (!Table1->Eof)
{
Record="";
for (int i=0;i<FieldNum;i++)
{
TmpFie="";
TmpFie=Table1->FieldByName(FieName)->AsString;
fwrite(&amp;TmpFie,FieLength,1,fp);
}
Table1->Next();
}
return ((ftell(fp)-SeekNum)/ RecordLength);
}
//----------------------------------------------------------------------------
int __fastcall TForm1::ReadRecord()
{
fclose(fp);
fp=fopen(SaveDialog1->FileName.c_str(),"rb+");
fseek(fp,SeekNum,0);
int Counter;
AnsiString FieStr1[50];
while (!feof(fp))
{
for (int i=0;i<FieldNum;i++)
{
if(fread(&amp;FieStr1,FieLength,1,fp))
StringGrid1->Cells[i+1][Counter+1]=FieStr1;
else
break;
}
Counter=Counter+1;
}
return (ftell(fp)-SeekNum)/RecordLength;

}
//----------------------------------------------------------------------------
void __fastcall TForm1::RefreshGrid()
{
StringGrid1->ColCount=FieldNum+1;
StringGrid1->RowCount=RecordNum+2;
StringGrid1->FixedRows=1;
StringGrid1->FixedCols=1;
StringGrid1->ColWidths[0]=12;
for (int i=0;i<FieldNum;i++)
{
StringGrid1->Cells[i+1][0]=FieName1;
StringGrid1->ColWidths[i+1]=40+FieLength*2;
}
}
//----------------------------------------------------------------------------
int __fastcall TForm1::First()
{
fseek(fp,SeekNum,0);
return 1;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Last()
{
fseek(fp,-0,2);
return (ftell(fp)-SeekNum)/RecordLength;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Next()
{
if(!fseek(fp,RecordLength,1)) return -1;
else
return ((ftell(fp)-SeekNum)/RecordLength);
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Append()
{
fseek(fp,sizeof(int),0);
RecordNum=RecordNum+1;
fwrite(&amp;RecordNum,sizeof(int),1,fp);
fseek(fp,-0,2);
for (int i=0;i<FieldNum;i++)
{
fwrite(&amp;FieStr,FieLength,1,fp);
}
return (ftell(fp)-SeekNum)/RecordLength;
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Insert()
{
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Delete()
{
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Edit()
{
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Local()
{
}
//---------------------------------------------------------------------------
int __fastcall TForm1::Find()
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N1Click(TObject *Sender)
{
OpenDialog1->Filter="Paradox 7.0 files(*.DB)|*.DB|Any file(*.*)|*.*";
OpenDialog1->Title="请选择要转换的文件";
OpenDialog1->Execute();
if(FileExists(OpenDialog1->FileName)&amp;&amp;(OpenDialog1->FileName!=""))
{
Table1->Active=false;
Table1->DatabaseName=ExtractFilePath(OpenDialog1->FileName);
Table1->TableName=OpenDialog1->FileName;
Table1->Active=true;
GetDBFieldNum();
GetRecordNum();
GetFieldInf();
N3Click(NULL);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N3Click(TObject *Sender)
{
SaveDialog1->Filter="Binary file (*.Dat)|*.Dat";
SaveDialog1->Title="保存到文件";
if(SaveDialog1->Execute()&amp;&amp;(SaveDialog1->FileName!=""))
{
if ((fp=fopen(SaveDialog1->FileName.c_str(),"wb+"))!=NULL)
WriteFileHead();
WriteRecord();
ReadFileHead();
RefreshGrid();
ReadRecord();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::X1Click(TObject *Sender)
{
Table1->Active=false;
Form1->Close();
}
//---------------------------------------------------------------------------

上面的代码用到的全局变量如下:
FILE *fp;
int FieldNum,RecordNum,RecordLength;
AnsiString FieStr[50];
AnsiString FieName[50],FieName1[50];
AnsiString FieType[50];
int FieLength[50];
int SeekNum;
请问这部分代码有什么缺陷?
欢迎指正。。。。
我想删除字节使用文件截断函数是可行的(谢谢斑竹和各位大侠)
 
加上索引功能会更好一些。
 
如何加入索引呢?请帮助解决?(我本人分数很少)
 
各位大侠,我在数据表转换到二进制数据库文件中给每个字段都添加了一个识别符号。
 
记录数不多就不必做索引了,如果很多,可以建立一个文件,这个文件是索引对照表
比如以姓名做索引:

1 张三
2 李四
3 王二麻子
知道是哪条记录,可以快速定位。节省时间。
 
注意索引也必须维护,不必须的话就不用建索引了。
 
后退
顶部