我根本不擅长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;
}
非常感谢任何帮助。
答案 0 :(得分:3)
对于您的文件问题,我强烈建议您查阅C标准库文档。
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 - 1
与0x80
组合在一起(十六进制为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;
}