有没有办法使用fwrite方法读取变量(动态数组)而不是FILE *,或者某种替代方法可以让我这样做?我需要读取包含16位块的二进制文件,但只读取每个块的最后12位。理想情况下,我想要这样的东西:
fwrite(&(x+4),sizeof(x)-4,1,var);
但是目前,我无法直接写入var,只能写入文件。
我知道它可能使用bitmasks / bitops,但这是一种更简单的方式,所以我更愿意在可能的情况下使用它。
答案 0 :(得分:1)
不,fwrite
写一些像文件一样被访问的内容(FILE *)。
也许您想使用sprintf
将数据格式化为字符串?
答案 1 :(得分:0)
C是面向字节的,而不是面向位的。
读取两个16位整数,并通过削减前4位将它们组合成24位(3个字节)。
for(;;) {
uint8_t current;
uint16_t d[2];
if(fread(d,sizeof d,2,my_file) != 2) //convert the int if it's in the
//oposite endian of your host.
return;
current = (d[0] & 0xff0) >> 4) ;
if(fwrite(¤t,1,1,my_outfile) != 1) //or store it in an array.
return;
current = (d[0] & 0xf) << 4;
current |= (d[1] & 0xf00) >> 8) ;
if(fwrite(¤t,1,1,my_outfile) != 1) //or store it in an array.
return;
current = d[1] & 0xff;
if(fwrite(¤t,1,1,my_outfile) != 1) //or store it in an array.
return;
}
Alternativly一次读取一个16位int:
int state = 0;
uint8_t current;
for(;;) {
uint16_t d;
if(fread(&d,sizeof d,1,my_file) != 1) //convert the int if it's in the
//oposite endian of your host.
return;
switch(state)
case 0:
current = (d & 0xff0) >> 4) ;
if(fwrite(¤t,1,1,my_outfile) != 1) //or store it in an array.
return;
current = (d & 0xf) << 4;
state = 1;
break;
case 1;
current |= (d & 0xf00) >> 8) ;
if(fwrite(¤t,1,1,my_outfile) != 1) //or store it in an array.
return;
current = d & 0xff;
if(fwrite(¤t,1,1,my_outfile) != 1) //or store it in an array.
return;
state = 0;
break;
}
}
答案 2 :(得分:0)
读取16位。假设CHAR_BIT为8(通常)为2个字节:
size_t chk;
unsigned char data16[2];
chk = fread(data16, 2, 1, file);
if (chk != 1) {
/* handle error */
}
现在,根据字节顺序问题,只需忽略读取的16位中的右4:
data16 has, for instance: 01000101 11101011 (data16[0] == 0x45; data16[1] == 0xeb) and you want these bits: ^^^^^.^^ ^..^^^.^ so ... mask and shift!
/* mask and shift, bit by bit */
data12[0] = 0;
data12[0] |= !!(data16[0] & (1 << 7)) << 3;
data12[0] |= !!(data16[0] & (1 << 6)) << 2;
data12[0] |= !!(data16[0] & (1 << 5)) << 1;
data12[0] |= !!(data16[0] & (1 << 4)) << 0;
data12[1] = 0;
data12[1] |= !!(data16[0] & (1 << 3)) << 7;
data12[1] |= !!(data16[0] & (1 << 1)) << 6;
data12[1] |= !!(data16[0] & (1 << 0)) << 5;
data12[1] |= !!(data16[1] & (1 << 7)) << 4;
data12[1] |= !!(data16[1] & (1 << 4)) << 3;
data12[1] |= !!(data16[1] & (1 << 3)) << 2;
data12[1] |= !!(data16[1] & (1 << 2)) << 1;
data12[1] |= !!(data16[1] & (1 << 0)) << 0;
答案 3 :(得分:0)
编辑添加更好的答案
从注释中看起来你想要压缩一个缓冲区 - 一个16位整数数组,通过剥离4位并将它们打包在一起,对吗?
这段代码可以解决问题:
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
typedef unsigned int UINT32 ;
typedef unsigned short UINT16 ;
void compress( UINT16 *buf , int *cnt )
{
UINT16 *src = buf ; // where we're copying from
UINT16 *tgt = buf ; // where we're copying to
UINT16 *limit = buf + *cnt ; // endpoint address
UINT16 bits = 0x0000 ;
int state = 0 ;
while ( src < limit )
{
switch ( state )
{
case 0 :
bits = (*src++ & 0x0FFF ) << 4 ;
state = 1 ;
break ;
case 1 :
bits |= (*src & 0x0F00 ) >> 8 ;
*tgt++ = bits ;
bits = (*src++ & 0x00FF ) << 8 ;
state = 2 ;
break ;
case 2 :
bits |= (*src & 0x0FF0 ) >> 4 ;
*tgt++ = bits ;
bits = (*src++ & 0x000F ) << 12 ;
state = 3 ;
break ;
case 3 :
bits |= (*src++ & 0x0FFF ) ;
*tgt++ = bits ;
bits = 0x000 ;
state = 0 ;
break ;
}
}
if ( state != 0 )
{
*tgt++ = bits ;
}
// hand back the new size ;
*cnt = (tgt - buf ) ;
while ( tgt < limit )
{
*tgt++ = 0x0000 ;
}
return ;
}
int main( int argc, char* argv[])
{
UINT16 buf[] = { 0xF123 , 0xE456 , 0xD789 , 0xCABC , 0xBDEF , } ;
int bufl = sizeof(buf) / sizeof(*buf) ;
compress( buf , &bufl ) ;
// buf now looks like { 0x1234 , 0x5678 , 0x9ABC , 0xDEF0 , 0x0000 }
return 0 ;
}
原始回答
如果你真的想要从一个文件中读取 16位结构并且有12个有趣的位和4个未使用的(或不是非常有趣的)位,并且你想要避免位杂乱,那么你可以使用位字段。
请注意,在这些内容的工作原理标准下,实现获得了很多的余地,因此它至少不可移植:您可能需要调整结构对齐和可能的字段顺序,具体取决于在底层CPU上。您将注意到我使用#pragma pack(2)
将结构强制转换为16位大小 - 适用于Visual Studio 2010 C ++。 YMMV等等。
[你确定你不想掩盖你不想要的东西?]
无论如何,一旦你处理了所有这些,类似下面的代码应该适合你:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#pragma pack(2) // necessary to get correct alignment
typedef struct
{
unsigned short unused : 4 ;
unsigned short value : 12 ;
} CHUNK ;
#define BUFFER_CHUNKS ((size_t)8192)
void process( FILE*input )
{
CHUNK *buf = (CHUNK*) calloc( BUFFER_CHUNKS , sizeof(CHUNK) ) ;
size_t bufl = BUFFER_CHUNKS * sizeof(CHUNK) ;
int chunks = 0 ;
while ( 0 > (chunks=(int)fread( (void*)buf , sizeof(CHUNK) , BUFFER_CHUNKS , input ) ) )
{
for ( int i = 0 ; i < chunks ; ++i )
{
int value = buf[i].value ;
printf( "%d: %d\n" , i , value ) ;
}
}
return ;
}
祝你好运!