Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

About the access of the dbf file 1

Status
Not open for further replies.

Vinay355

Programmer
Dec 12, 2006
12
IN
Hi,
i Have wrote the code to access the file in C Builder. but i have the problem in reading the end byte which represents the end of file. I need to stop exectuing my program when i get this character. I dont know how to compare it as the character is a binary.

Thanks in advance,
Vinay
 
Most of the time, I use the "\#" construct to compare such characters. For example, "\n" = newline or 0A hex. Do you know the hex equivalent of the character you are looking for? You can also use that.


James P. Cottingham
-----------------------------------------
[sup]I'm number 1,229!
I'm number 1,229![/sup]
 
Show the code that you have written to read the file, the way that you determine end of file depends on how you have opened and are reading the file.
 
I knpw the he value of the eof file character which is equal to 255, the last char in the ascii set..But when i convert char into hex, it not putiing the end in reading the file..
Please help me..
I will give my code in the next mail..

Bye
vinay
 
Ok, Vinay, the eof character most likely isn't 255, I think you're referring to the value of EOF, which is generally -1. The Hex equivalent of -1 is 0xFF, which if is assigned to an unsigned char becomes 255, which is also 0xFF. EOF is the value that is returned by file i/o functions (i.e. fscanf, fgets etc.) when there is no more data to be read, not the value of the actual end of file marker stored in the ascii file.

If you are working with ascii text files under windows, the actual eof marker is going to be ascii value 26. If you open the text file in binary mode, you will actually be able to read the eof marker, however if opened in text mode, you never will. If you are not working with text files, but binary files, there is no eof marker, you just read until you have reached the end of the file as determined by where the file pointer is in the file.

If this doesn't make sense, post some code to show what you are trying to do.
 
Hi friends,
Thanks for ur responses..
This is my code....

I am openeing my file as a text file as earlier metnioned.So what must be my last char to end the reading...

Thnaks in advance,
Vimnay




FILE *stream;
unsigned static char c;
unsigned int TotalCount = 0;
unsigned char *HeaderBuffer;
HeaderBuffer = new unsigned char[1000];
string FieldNames[25];
unsigned char *FieldType;
FieldType = new unsigned char [100];
unsigned char *FieldLength;
FieldLength = new unsigned char [100];
unsigned char *DecimalCount;
DecimalCount = new unsigned char [100];

String *DataRecord;
DataRecord = new String [100];

unsigned int NoOfRecords = 0;
unsigned int NoOfBytesInHeader = 0;
unsigned int NoOfBytesInRecord = 0;
unsigned int DataSegment = 0;
bool LastCharExtractor = true;
unsigned char LastCharacter;
unsigned char DataFlag;
unsigned int RecordNumber = 1;
string DataRecordStr;

stream = fopen(OpenDBFFile->Files->Strings[0].c_str(), "r");

if (stream)
{
while(( (int) (c = getc(stream)))!= 255)
{
int f = c;
/* if(c == '\0')
c = '#';
else
c = c; */
switch(DataSegment)
{
case 0: // Header Information...........................
/*
if(TotalCount < 11)
{ */
HeaderBuffer[TotalCount] = c;
// }

/* else */ if(TotalCount == 11)
{
// Bytes 8 and 9 represents the number of bytes in the header.........
NoOfBytesInHeader = (int)HeaderBuffer[8] + (int )HeaderBuffer[9] * pow(2,8);
// Bytes 10 and 11 represents the no of bytes for the records.........
NoOfBytesInRecord = (int)HeaderBuffer[10] + (int) HeaderBuffer[11] * pow(2,8);
// Bytes 4,5,6 and 7 represents the no. of records.....................
NoOfRecords = HeaderBuffer[4] + (int) HeaderBuffer[5] * pow(2,8)+ (int)HeaderBuffer[6] + (int) HeaderBuffer[7] * pow(2,8);

DBFDataStrGrid->RowCount = NoOfRecords;
DataSegment++;
LastCharacter = c;
}
break;

case 1:
/* if(TotalCount < (NoOfBytesInHeader))
{
if(LastCharExtractor == true)
{
HeaderBuffer[TotalCount] = LastCharacter;
LastCharExtractor = false;
} */
HeaderBuffer[TotalCount] = c;
// }
/* else */ if(TotalCount == (NoOfBytesInHeader - 2))
{
LastCharExtractor = true;
LastCharacter = c;
int ByteSkipper = 0;
for(int i = 32; i < (NoOfBytesInHeader - 2); i++) // 10 bytes for the field name......
{
switch(ByteSkipper)
{
case 0: // Extracting the field names.........................
if(HeaderBuffer!= '\0')
{
FieldNames[FieldNoIncrement]+= HeaderBuffer;
}
else if (HeaderBuffer== '\0') // 1 byte for the decimal count in binary.............
{
FieldNames[FieldNoIncrement]+= '\0';
ByteSkipper++;
}
break;


case 1: // Extracting the field type...........
if(HeaderBuffer != '\0')
{
// 1 byte for the field type........
FieldType[FieldNoIncrement] = HeaderBuffer;
ByteSkipper++;
// skip 4 bytes and 1 byte field length in binary.....
i = i+4;
}

break;

case 2: // Extracting the field length............
if(HeaderBuffer != '\0')
{
unsigned char d = HeaderBuffer;
FieldLength[FieldNoIncrement] = HeaderBuffer;
}
else
{
FieldLength[FieldNoIncrement] = 0;
}
ByteSkipper++;
break;

case 3: // Extracting the decimal Count..............
{
unsigned char d = HeaderBuffer;
/* if((FieldType[FieldNoIncrement] == 'N')||(FieldType[FieldNoIncrement] == 'F'))
{
if(HeaderBuffer != '\0')
{
DecimalCount[FieldNoIncrement] = (int)HeaderBuffer;
i = i;
}
else
{
DecimalCount[FieldNoIncrement] = (int) 0;
i = i;
}
ByteSkipper = 0;
i = i + 14;
FieldNoIncrement++;
}
else
{
DecimalCount[FieldNoIncrement] = (int) 0;
i = i;
ByteSkipper = 0;
i = i + 14;
FieldNoIncrement++;
} */

DecimalCount[FieldNoIncrement] = d;
FieldNoIncrement++;
ByteSkipper = 0;
i = i + 14;
}
break;

} // End Of Switch Statement...........
}// End of For loop.............................

DBFDataStrGrid->ColCount = FieldNoIncrement;
for(int i = 0; i <(FieldNoIncrement);i++ )
{
DBFDataStrGrid->Cells[0] = (String) FieldNames.c_str();
i = i;
}
DataSegment++;
} // End of if statement.............................
break;

case 2: // Records Fetching.................................
{

if(LastCharExtractor == true)
{
DataFlag = LastCharacter;
LastCharExtractor = false;
}
if(DataFlag == ' ')
{
if(TotalCount < ((NoOfBytesInHeader - 1) + NoOfBytesInRecord* RecordNumber))
{
DataRecordStr += c;
}
else if(TotalCount == ((NoOfBytesInHeader - 1) + NoOfBytesInRecord* RecordNumber))
{
int FieldValExtract = 0;
int DataExtractPointer = 0;

DataFlag = c;
String RecordSplit;
int x = DataRecordStr.size();

do
{
RecordSplit = "";
switch(FieldType[FieldValExtract])
{
case 'C': //Representing the Character Varialbles......
for(int i = DataExtractPointer ; i < (DataExtractPointer + FieldLength[FieldValExtract]) ; i++)
{
RecordSplit += DataRecordStr;
}
DBFDataStrGrid->Cells[FieldValExtract+ 1][RecordNumber] = RecordSplit;
DataExtractPointer = DataExtractPointer + FieldLength[FieldValExtract];

break;

case 'D':
{
int YMDSeparator = 0;
for(int i = DataExtractPointer ; i < (DataExtractPointer + FieldLength[FieldValExtract]) ; i++)
{
YMDSeparator++;
RecordSplit += DataRecordStr;
switch(YMDSeparator)
{
case 4:
RecordSplit += "/";
break;
case 6:
RecordSplit += "/";
break;

default:
break; }
}

DBFDataStrGrid->Cells[FieldValExtract][RecordNumber] = RecordSplit;
DataExtractPointer = DataExtractPointer + FieldLength[FieldValExtract];
}

break;

case 'N':
{
for(int i = DataExtractPointer ; i < (DataExtractPointer + FieldLength[FieldValExtract]) ; i++)
{
RecordSplit += DataRecordStr;
}
//String RecordSplitFloat;
//RecordSplitFloat = StrToInt(RecordSplit)/ pow(10,(int) DecimalCount[FieldValExtract]);
DBFDataStrGrid->Cells[FieldValExtract][RecordNumber] = RecordSplit;
DataExtractPointer = DataExtractPointer + FieldLength[FieldValExtract];
}
break;

case 'L':
for(int i = DataExtractPointer ; i < (DataExtractPointer + FieldLength[FieldValExtract]) ; i++)
{
RecordSplit += DataRecordStr;
}
DBFDataStrGrid->Cells[FieldValExtract+ 1][RecordNumber] = RecordSplit;
DataExtractPointer = DataExtractPointer + FieldLength[FieldValExtract];
break;

case 'M':
for(int i = DataExtractPointer ; i < (DataExtractPointer + FieldLength[FieldValExtract]) ; i++)
{
RecordSplit += DataRecordStr;
}

RecordSplit = "Memo";
DBFDataStrGrid->Cells[FieldValExtract+ 1][RecordNumber] = RecordSplit;
DataExtractPointer = DataExtractPointer + FieldLength[FieldValExtract];
break;

default:
break;


}
FieldValExtract++;
}while(FieldValExtract < FieldNoIncrement);

RecordNumber++;
DataRecordStr = "";
//DataRecordStr += c;
}
}
else
{
// LastCharacterExtract = true;
DataFlag = c;

}
}
break;
default:

break;

} // End of Main Switch........................................

TotalCount++;
}// End Of File accessing...........................

fclose(stream);
} // End Of File Accessing.......................

delete [] HeaderBuffer;
delete [] FieldNames;
delete [] FieldLength;
delete [] DecimalCount;
delete [] FieldType;
delete [] DataRecord;
 
Replace
Code:
while(( (int) (c = getc(stream)))!= 255)
with
Code:
while(c = getc(stream))

I haven't tried it so I can't say if that will work or not.

I use getline and strings for all my streams The following code works.
Code:
    // Read and parse (loop)
    std::ifstream InFile; // stream set up
    InFile.open(FullFileStr.c_str());

    if (!InFile)                        // Opps
    {
        // Something went wrong
        MessageDlg("Could not open file for processing!", mtError, TMsgDlgButtons() << mbOK, 0);
        Screen->Cursor = crDefault;
        return;
    }                                   // Opps
    else                                // Process file
    {
        InFile.unsetf(std::ios::skipws); // don't skip white space

        int LineInt = 0;
        std::string ImpLine;             // import line
        while (std::getline(InFile, ImpLine, '\n'))  // Process each line
        {
             // Do the work here
        }                               // Process each line
        InFile.close();
    }                                   // Process file


I prefer to work with strings so I don't have to worry about allocating the resources/space manually. I don't process character by character and if I did I would pull the string in and look at each character in the string.

Just a thought.


James P. Cottingham
-----------------------------------------
[sup]I'm number 1,229!
I'm number 1,229![/sup]
 
Your problem is that you are mixing signed and unsigned variables. getc returns a signed integer, but your variable c is an unsigned char. getc doesn't ever return 255, it returns -1 (EOF) on end of file, but as I mentioned earlier, -1 (EOF) when assigned to an unsigned char becomes 255. To illustrate this, execute the following code:

Code:
  cout << (int) (unsigned char) EOF
       << "\n";

  cout << (int) (char) EOF
       << "\n";

To fix your code for reading from your input file, change c to a signed char (not sure why you need it to be a static variable, but I'm sure you have your reasons), then change your while statement so your code looks like the following:

Code:
static char c;
 .
 .
 .
while ((c = getc(stream)) != EOF)
{
.
.
.

I didn't delve too much in detail into the rest of your code, but there are some potential pitfalls depending on what your input is & without seeing your input I can't tell for sure. As an example looking at your code such as:
Code:
  NoOfBytesInHeader = (int)HeaderBuffer[8] + (int) HeaderBuffer[9] * pow(2,8);

It looks like you could have values < ascii 32 (' ') written to your data file, if that's the case, then you really have a binary file, not a text file which could cause potential trouble. If on the other hand your data values (such as HeaderBuffer[8] and HeaderBuffer[9]) are going to be ascii numeric chars ('0'..'9'), then casting them to ints isn't going to give you the correct values, you need to convert them to their corresponding integer values ('0' to 0 and '1' to 1 etc.)

Also, just as a friendly reminder, it helps a lot to read your code if you put the [ignore]
Code:
[/ignore] tags around it.

Good luck.
 
Hi itsgsd,
getc() doesnt returns the signedchar.it returns the unsigned char.I have declared earlier as char and not able to process the character by character as ascii values are defined from 0 to 255 not from -125 to 125. I think that u have understood it. When i am processing , i have compared with EOF too, but no use.what shall i do? This is only for ur kind information.

Bytes per header = comes low byte first and then high byte.I have to equi. of it. So what can i do? The lenght of the header and rows will be in binary format.SO how can i can read them when i want to know the lenght of the header , record and no. of records in the dbf file.

Thanks for ur suggestions
 
>> getc() doesnt returns the signedchar.it returns the unsigned char.

Actually, getc() returns a signed int, not a char (signed or unsigned), which means it can return values of 0-255 for your ascii characters or it can return -1 which is EOF. ascii 255 is not the same as EOF, but it appears the same because you are assigning it to an unsigned char. After looking at your code more closely, it looks like you don't need c to be a char at all, simply defining c as an int will take care of the EOF/ascii 255 ambiguity.

Code:
int c;
 .
 .
 .
          while((c = getc(stream))!= EOF)
 . 
 .
 .

I think the main source of your problem is that your data file is not a text file, it is a binary file. You are probably reading the file ok until you come to the end of file marker for a text file (ascii 26 dec, 0x1a hex). It will also cause you a problem if you actually have a value of 255 in your data file because in your code you will detect this as EOF when it really isn't. Try opening it as a binary file instead of a text file and see what happens.

Code:
    stream = fopen(OpenDBFFile->Files->Strings[0].c_str(), "rb");
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top