📄 readjnb.c
字号:
/*------------------------------------------------------------------------------*
* File Name: readjnb.c *
* Creation: GRD 8/7/2001 *
* Purpose: OriginC Source C file *
* Copyright (c) OriginLab Corp. 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 *
* All Rights Reserved *
* *
* Modification Log: GRD 2003.01.14 No new worksheet for Text+Binary *
*------------------------------------------------------------------------------*/
#include <origin.h>
#include "readjnb.h"
#define DATA_RECORD 1
#define NAME_RECORD 2
#define EOF_RECORD 134
#define FILETYPE1 1
#define FILETYPE2 2
#define ERR1 1 // Could not open file.
#define ERR2 2 // File truncated.
#define ERR3 3 // This file type is unknown.
#define ERR4 4 // Failed to identify more records.
#define ERR5 5 // Failed to find records.
// The main function
int readjnb(String filename, String strWksName)
{
file fid; // The file handle
uint iFileSize = 0; // The file size
uint iFileType = 0; // Type 1 or Type 2
uint iRecordType = 0; // Record types allowed : Data, Name and EOF
uint iBytesRead = 0; // Generic, returns bytes read using file.Read()
uint iTemp = 0; // Generic
uint iStatus = 0; // Status/Error of import
uint iNumCols = 0; // Number of Columns
uint iOffset = 0; // Offset to next record
// Begin code
if( fid.Open(filename, file::modeRead) )
{
// What size is the file
iFileSize = fid.SeekToEnd();
// Rewind
fid.SeekToBegin();
iBytesRead = fid.Read(&iTemp, sizeof(iTemp));
fid.SeekToBegin();
if((iTemp & 255) == 0)
{
// This is a worksheet file, start with the header
iStatus = read_header(fid, &iFileType, &iNumCols, iFileSize);
if(iStatus)
{
fid.Close();
return iStatus;
}
// Locate the first record
iStatus = seek_start(fid, iFileSize, &iOffset, &iRecordType);
if(iStatus)
{
fid.Close();
return iStatus;
}
// Process the records
iStatus = read_file(fid, &iOffset, iFileSize, iFileType, &iRecordType);
if(iStatus)
{
fid.Close();
return iStatus;
}
}
else
{
// This is a text file
fid.Close();
// No new worksheet for Text+Binary
return 2;
// In case I decide to handle these ...
if((iTemp & 255) == 255)
{
// This is a long text file
iTemp = (iTemp&16776960)/256;
LT_execute("Type -a $OMRDJNB.Warnings.Text;");
}
else
{
// This is a short text file
iTemp&255;
LT_execute("Type -a $OMRDJNB.Warnings.Text;");
}
}
}
else
{
// Couldn't open the file
iStatus = 1;
printf("Error %u in %s:\n", iStatus, filename);
LT_execute("Type -a $OMRDJNB.Errors.Err1;");
}
fid.Close();
return iStatus;
}
// Header contains the File Type and the Number of Columns
int read_header(file &fid, uint *piFileType, uint *piNumCols, uint iFileSize)
{
const int cM0 = 360704;
const int cM1 = 28674;
const int cM2 = 8324;
uint iBytesRead = 0;
uint iValue = 0;
uint iJunk = 0;
ushort iShort = 0;
uint iPos = 0;
uint iOffset = 0;
char cFlag1 = 0;
char cFlag2 = 0;
// Must read this value
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // 0x00 0x81 0x05 0x00
if(cM0 != iValue)
{
printf("Error : 21\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 21;
}
// True file size should match internal description
iBytesRead = fid.Read(&iValue, sizeof(iValue));
if(iFileSize != (iValue + 8)) LT_execute("type -a OMRDJNB.Warnings.warn1");
// Must read this value
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // 0x02 0x70 0x00 0x00
if(cM1 != iValue)
{
printf("Error : 22\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 21;
}
// Skip over standard header stuff
iBytesRead = fid.Read(&iOffset, sizeof(iOffset));
iPos = fid.GetPosition();
iPos += iOffset;
fid.Seek(iPos, file::begin);
// Must read this value
iBytesRead = fid.Read(&iShort, sizeof(iShort)); // 0x84 0x20
if(cM2 != iShort)
{
printf("Error : 23\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 23;
}
// Establish file Type
iBytesRead = fid.Read(&cFlag1, sizeof(cFlag1));
iBytesRead = fid.Read(&cFlag2, sizeof(cFlag2));
if(3 != cFlag1 && 5 != cFlag1)
{
printf("Error : 24\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 24;
}
iBytesRead = fid.Read(&iValue, sizeof(iValue));
if(8 != iValue && 16 != iValue)
{
printf("Error : 25\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 25;
}
// Set the file Type and get the number of columns
iBytesRead = fid.Read(&iJunk, sizeof(iJunk));
if(8 == iValue)
{
*piFileType = FILETYPE1;
iBytesRead = fid.Read(&iShort, sizeof(iShort));
*piNumCols = (uint) iShort + 1;
iBytesRead = fid.Read(&iShort, sizeof(iShort)); // maxRows0 - not needed
}
else
{
*piFileType = FILETYPE2;
iBytesRead = fid.Read(&iJunk, sizeof(iJunk));
iBytesRead = fid.Read(&iValue, sizeof(iValue));
*piNumCols = iValue + 1;
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // maxRows0 - not needed
}
// Update the worksheet with the number of columns
LT_set_var("ncols", *piNumCols);
LT_execute("if(ncols > wks.ncols) wo -a $(ncols - wks.ncols);");
// This 'short-circuits' the rest of the code if this is Type1 format
// Return of 99 means use old SPW routine to read stream stored in TEMPfolder
// When we have a routine that reads long double, we can eliminate this line
if(*piFileType == 1) return 99; else return 0;
}
// Skip over unprocessed record types, establish current record type and offset to next record
int seek_start(file &fid, uint iFileSize, uint *piOffset, uint *piRecordType)
{
uint iPos = 0;
uint iMax = 0;
uint iLoop = 0;
uint iBytesRead = 0;
char cChar[4];
iPos = fid.GetPosition();
iMax = iFileSize - 4;
// An infinite loop
for(iLoop = 0; iLoop == 0 && iPos < iMax; )
{
iBytesRead = fid.Read(&cChar, 4);
*piRecordType = (int) cChar[0];
if(1 == cChar[0] || 2 == cChar[0])
{
if(32 == cChar[1] && 5 == cChar[2] && 0 == cChar[3])
iLoop = 1;
}
else
{
iPos +=1;
fid.Seek(iPos, file::begin);
}
} // End for loop
if(!iLoop)
{
LT_execute("type -a $OMRDJNB.Warnings.eof;");
return 31;
}
iBytesRead = fid.Read(&iLoop, sizeof(iLoop)); // this is the offset to the next record
*piOffset = iLoop;
return 0;
}
// Apologies for the long function. This was translated from LabTalk.
// Read the file records
int read_file(file &fid, uint *piOffset, uint iFileSize, uint iFileType, uint *piRecordType)
{
uint iBytesRead = 0;
uint iValue = 0;
uint iPos = 0;
uint iLastPos = 0;
uint iStatus = 0;
uint iDone = 0;
char cChar = 0;
uint iThisCol =0;
uint iNumRows = 0;
uint iThisRow = 0;
uint iIgnore = 0;
double dBlockFlag = 0;
string sColName; // this didn't work too well
char cBuffer[256]; // try this
unsigned char cTag = 0;
double dValue = 0;
uint iLength = 0;
const uint cM2 = 83914754;
const uint cM3 = 235085952;
const uint cM4 = 1253505;
const uint cM5 = 201662592;
const uint cM6 = 1253511;
const uint cM7 = 6;
const uint cM8 = 0;
const uint cM9 = 83914754;
const uint cM10 = 0;
const uint cM11 = 8322;
const uint cM12 = 16;
const uint cM13 = 204931;
const uint cM14 = 8;
const uint cM15 = 256;
const uint cM16 = 336003;
const uint cM17 = 16;
// Set up an infinite loop with no third expression
for(iDone = 0; iDone == 0; )
{
iLastPos = fid.GetPosition();
switch(*piRecordType)
{
case DATA_RECORD:
// Reading Data
// Must read this value
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // 0x02 0x70 0x00 0x05
if(cM2 != iValue)
{
printf("Error : 51\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 51;
}
// Must read this value
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // 0x00 0x00 0x00 0x00
if(cM8 != iValue)
{
printf("Error : 52\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 52;
}
switch(iFileType)
{
case FILETYPE1:
// This code does not handle Type1
break;
case FILETYPE2:
// Must read this value
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // 0x80 0x20 0x05 0x0C
if(cM5 != iValue)
{
printf("Error : 53\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 53;
}
iBytesRead = fid.Read(&iThisCol, sizeof(iThisCol)); // indexed from zero
// Must read this value
iBytesRead = fid.Read(&iValue, sizeof(iValue)); // 0x87 0x20 0x13 0x00
if(cM6 != iValue)
{
printf("Error : 54\n");
LT_execute("type -a $OMRDJNB.Errors.general;");
return 54;
}
iBytesRead = fid.Read(&iIgnore, sizeof(iIgnore)); // Ignore this
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -