需要一些帮助将此C代码移植到C#

时间:2010-07-17 04:53:48

标签: c# c compression

我根本不擅长c。我试图使用这篇wikipedia文章来捕捉C代码在C#中所做的事情的本质。但是我的版本完全不同,并没有达到与C代码相同的压缩效果。因此,我想将以下代码从C语言移植到C#。但是,我不需要它来读/写文件。

我不熟悉文件读写如何在C中工作。因此所有与文件相关的绒毛都让我感到困惑。这些行也有点令人困惑:token = i - 1 | 0x80;length = (token & ~0x80) + 1;

/******************************************************************************
 * LoadRLE / SaveRLE - Load and save binary data using RLE compression.
 *  Run-length tokens have a set MSB, while data tokens have a cleared
 *  MSB. The value of the token's remaining bits plus one indicates the
 *  length of the block. The minimum run length is three bytes, while
 *  the maximum is 128.
 *
 *  data - Array holding data to load or save.
 *  size - Size of the data array.
 *  file - The file pointer to use.
 *  return - Total number of bytes read from or written to data[].
 */
size_t SaveRLE (unsigned char data[], size_t size, FILE *file)
{
    unsigned char token;
    unsigned int i;
    size_t total = 0;

    while(size)
    {
        /*This loop identifies blocks of repeating data:*/
        i = 2;
        while(i < size && i < 128 &&
            data[i] == data[i - 1] && data[i - 1] == data[i - 2])
            i++;
        /*If repeating data was found, save it:*/
        if(i > 2){
            token = i - 1 | 0x80;
            if(!fwrite(&token, 1, 1, file))
                return total;
            if(!fwrite(data, 1, 1, file))
                return total;
            data += i, size -= i, total += i;
        }

        /*This loop identifies blocks of non-repeating data:*/
        i = 0;
        while(i < size && i < 128 && (i + 2 > size ? 1 :
            data[i] != data[i + 1] || data[i + 1] != data[i + 2]))
            i++;
        /*If non-repeating data was found, save it:*/
        if(i){
            token = i - 1;
            if(!fwrite(&token, 1, 1, file))
                return total;
            if(fwrite(data, 1, i, file) != i)
                return total;
            data += i, size -= i, total += i;
        }
    }

    return total;
}

size_t LoadRLE (unsigned char data[], size_t size, FILE *file)
{
    unsigned char token;
    unsigned int length;
    size_t total = 0;

    while(size && fread(&token, 1, 1, file)){
        length = (token & ~0x80) + 1;
        if (length > size)
            return total;
        if(token & 0x80){
            if(!fread(&token, 1, 1, file))
                return total;
            memset(data, token, length);
        }else{
            if(fread(data, 1, length, file) != length)
                return total;
        }
        data += length, size -= length, total += length;
    }
    return total;
}

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:3)

对于您的文件问题,我强烈建议您查阅C标准库文档。

fread fwrite

token = i - 1 | 0x80; 

我减1,|执行按位OR运算,在这种情况下设置令牌中的第8位。

length = (token & ~0x80) + 1;

token & ~0x80取0x80的所有位(所有位但高位)并按位AND(当两位都置位时位置位)。在这种情况下,它会返回除第8位以外的所有内容。

至于你的意思,请看一些关于RLE的文章。

答案 1 :(得分:1)

token = i - 1 | 0x80;

|符号是按位OR,因此它将i - 10x80组合在一起(十六进制为128)。我会把研究留给你按位操作。

length = (token & ~0x80) + 1;

&是按位AND,而~否定以下值(翻转1和0)。那样:

~1111000 = 00001111

顺便说一句,所有这些操作符都在C#中,并且或多或少地以相同的方式工作。

答案 2 :(得分:1)

/* 0 */
unsigned char token;
unsigned char data[];
FILE *file;

/* 1 */
if(!fwrite(&token, 1, 1, file))
    return total;

/* 2 */
if(!fwrite(data, 1, 1, file))
    return total;

/* 3 */
if(fwrite(data, 1, i, file) != i)
    return total;

/* 4 */
if(!fread(&token, 1, 1, file))
    return total;

/* 5 */
if(fread(data, 1, length, file) != length)
    return total;

/* 6 */
while(size && fread(&token, 1, 1, file))

/* 7 */
data += i;
data[i];

/* 0 */
int token; // I'm using 'int' here to easier read single byte from Stream object, in your C code 'token' variable does not overflow so there will be no problem with that is has other type then 'byte'
byte[] data;
int data_pos = 0; // instead of moving 'data' pointer use additional index variable
Stream file; // some stream to read/write bytes

try {
    /* 1 */
    file.WriteByte((byte)token);

    /* 2 */
    file.Write(data, data_pos, 1);

    /* 3 */
    file.Write(data, data_pos, i);

    /* 4 */
    if ((token = file.ReadByte()) < 0)
        return total;

    /* 5 */
    if (file.Read(data, data_pos, length) < length)
        return total;

    /* 6 */
    while((size != 0) && ((token = file.ReadByte()) >= 0))

    /* 7 */
    data_pos += i;
    data[data_pos + i];

} catch (IOException e) {
    return total;
}