我正在研究非常遗留的代码,即迁移到32位到64位的机器。通常写入文件的数据在32位工作正常但在64位机器上有问题。当我检查文件并发现它通常包含32位值的4的除法。我的意思是,如果我们在32位机器中有80个值,那么在64位机器中它将是20个。(大多数情况下)。我查看了下面的代码,无法理解一些功能。
为什么我们在写入File之前调用reverse函数。
反向功能的目的是什么。
在写函数中,尽管我们有任何数据类型,但我们总是写一个one_ascii值。
我试图采取一些代码来帮助我简要解释一下问题。请让我们 我知道是否需要提供更多信息。
class GdsHeader
{
public:
unsigned short rlen;
char record_type;
char data_type;
};
class GdsRecord
{
public:
#ifndef SWIG
union
{
short *two_int;
int *four_int;
double *eight_real;
char *one_ascii;
// void *v;
};
#endif
int length;
GdsRecord (); // { v = 0; length = 0; }
~GdsRecord () ;// { delete v; }
void len (int l, int type);
};
class GdsBlock
{
bool valid_block ();
int len;
public:
bool record_unred;
int header_ftell;
GdsHeader h;
GdsRecord r;
int array_size;
// bool re_read;
// GdsBlock () { re_read = false; }
GdsBlock () { record_unred = false; header_ftell = 0; }
void set (int rt, int dt, int sz)
{TBE;
h.record_type = rt; h.data_type = dt;
array_size = sz; r.len (sz, dt);TBX;
}
int read_header (FILE *);
void read_block (FILE *);
void write (FILE *);
void prt ();
};
void GdsRecord :: len (int l, int type)
{
switch (type)
{
case STREAM_Bit_array:
case STREAM_Short: l *= 2; break;
case STREAM_Long: l *= 4; break;
case STREAM_Double: l *= 8; break;
}
if (l > length)
{
l = ((l / 8) + 2) * 8;
if (one_ascii) delete [] one_ascii;
one_ascii = new char[l];
debug2.printf("GdsRecord::len new one_ascii len %d one_ascii %X\n",l, one_ascii);
length = l;
}
}
#ifndef sparc
static void reverse (int len, char *buf)
{
TBE;
char tmp[24];
int i;
for (i = 0; i < len; i++) tmp[i] = buf[i];
for (i = 0; i < len; i++) buf[i] = tmp[ (len - 1) - i];
TBX;
}
inline void reverse (int len, short *s) { reverse (len, (char *) s); }
inline void reverse (int len, int *s) { reverse (len, (char *) s); }
inline void reverse (int len, double *s) { reverse (len, (char *) s); }
inline void reverse (int len, unsigned char *s) {reverse (len, (char *) s); }
#endif
void GdsBlock :: write (FILE *outstr)
{
TBE;
debug.printf("GdsBlock::write %X\n",outstr);
int i, err;
char *c, tmp;
if (h.data_type == 3)
{
cout<<"Begin...blk.r.four_int[0] =>"<<r.four_int[0]<<endl;
}
if (!this)
error.printf_exit("GdsBlock::write error !this\n");
if (!outstr)
error.printf_exit ("GdsBlock::write Error - outstr == 0\n");
err = ferror(outstr);
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
if (err)
{ {
char *s = strerror (err);
fclose (outstr);
error.printf_exit ("GdsBlock::write error - %s, errno %d\n", s, err);
}
switch(h.data_type)
{
case 0: /* NO DATA */
h.rlen = 4;
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
break;
case 1: /* BIT ARRAY */
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
reverse (2, &r.two_int[0]);
#endif
h.rlen = (2 * array_size) + 4;
break;
case 2: /* TWO BYTE SIGNED INTEGER */
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
for (i = 0; i < array_size; i++) reverse(2,&r.two_int[i]);
#endif
h.rlen = (2 * array_size) + 4;
break;
case 3: /* FOUR BYTE SIGNED INTEGER */
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
#ifndef sparc
for(i = 0; i < array_size; i++)
{
cout<<r.four_int[i]<<endl;
int *temp = &r.four_int[i];
reverse(4,temp);
//print_stacktrace();
cout<<r.four_int[i]<<endl;
//r.four_int[i] = r.four_int[i] << 2 ;
}
#endif
h.rlen = (4 * array_size) + 4;
break;
case 5: /* EIGHT BYTE REAL */
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
#ifndef FPC
for (i = 0; i < array_size; i++) getr ((CONV *) (r.eight_real + i));
#endif
#ifdef FPC
for (i = 0; i < array_size; i++) fpc (r.eight_real + i);
#endif
h.rlen = (8 * array_size) + 4;
break;
case 6: /* CHARACTER ARRAY */
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
h.rlen = array_size + 4;
break;
default:
error.printf_exit("Error: bad record type %d in GdsBlock :: external\n", (int) h.data_type);
}
if (h.rlen % 2)
{
r.one_ascii[h.rlen] = 0;
h.rlen++;
}
cout<< __LINE__<<" "<<__PRETTY_FUNCTION__<<endl;
i = h.rlen - 4;
#ifndef sparc
c = (char *) &h.rlen;
tmp = c[0];
c[0] = c[1];
c[1] = tmp;
#endif
err = fwrite (&h, 1, sizeof (h), outstr);
if (err != sizeof(h))
{
err = ferror(outstr);
if (err)
{
char *s = strerror (err);
fclose (outstr);
error.printf_exit ("GdsBlock::write error - %s, errno %d\n", s, err);
}
fclose (outstr);
error.printf_exit("Error: bad header fwrite in GdsBlock :: write\n");
}
#if 1
err = fwrite (r.one_ascii, 1, i, outstr);
if (err != i)
{
err = ferror(outstr);
if (err)
{
char *s = strerror (err);
fclose (outstr);
error.printf_exit ("GdsBlock::write error - %s, errno %d\n", s, err);
}
fclose (outstr);
error.printf_exit("Error: bad record fwrite in GdsBlock :: write\n");
}
#endif
debug.printf("GdsBlock::write exit\n");
TBX;
}
答案 0 :(得分:2)
reverse()
会反转字节顺序,具体取决于平台。此处显示的似乎只是reverse()
的非SPARC版本,请参见endianness。
在写入文件之前反转字节顺序(即调用reverse()
)的原因是使文件格式平台(即字节序)独立。
答案 1 :(得分:1)
这是一些非常糟糕的代码。您在此处复制时也犯了一些错误:您复制了GdsRecord
两次,并且未声明i
中的GdsBlock::write
变量。
无论如何,这似乎应该是这样做的(而且我完全不确定它是否正确,取决于GdsRecord::len
的工作原理以及所有这些的确切含义 - 记录的字段和幻数是)以big-endian格式写int
。
然而,它似乎没有在big-endian中编写short
,这很奇怪,因为我很确定这意味着它无论如何都不会在sparc / x86互操作性中起作用。我不确定sparc对double
使用什么字节序,因此该部分可能会或可能不会起作用。此外,如果类型不是GdsBlock::write
,我无法提供仅仅部分写入数据的char
读数。