-2

I'm trying to write the binary number of 16-bit signed integer to a file. I searched a lot and ofcourse I found many examples which converts integer variables to binary. But in my case these functions will not be efficient, because I need to convert 50e6 samples/s. Calling a function to convert each sample will need a lot of computing time.

So what I want to do is:

int array[] = {233, 431, 1024, ...}
for (i = 0; i < sizeof(array); i++){
    fprintf(outfile, "%any_binary_format \n", array[i]);
}

result in the file should be:

0000000011101001
0000000110101111
0000010000000000
Niclas Resse
  • 31
  • 1
  • 9
  • 2
    Such format does not exist. You will have to write your own function. – Christian Gibbons Sep 24 '18 at 16:17
  • There is no standard specifier to achieve this. You have to write your own. – Osiris Sep 24 '18 at 16:18
  • 1
    When you say you want to write the 16 bits `0000000011101001`, do you want to write them as 16 bytes, 4 bytes, or 2 bytes? (I'm guessing 2, but the preceding three comments all presume 16.) – Steve Summit Sep 24 '18 at 16:22
  • 2
    It is not clear that you understand the difference between a binary file and a string of ASCII `'1'` and `'0'` digits. Your "_result in the file should be_" is ambiguous. If performance the issue you need binary - i.e. 2 bytes per sample, not 16 ASCII digits and a newline. That is probably what you meant but as @SteveSummit has pointed out, others have not interpreted it in that way. – Clifford Sep 24 '18 at 16:26
  • In your loop you are most likely accessing `array` out of bounds. – Osiris Sep 24 '18 at 16:27
  • OT: `sizeof(array)` ==> `sizeof array / sizeof *array` – Support Ukraine Sep 24 '18 at 16:30
  • I want my program to output a converted value but I don't want it to do any conversion. – Paul Childs Nov 24 '21 at 21:54

3 Answers3

1

fprintf is intended for formatted output - the formatting being "human readable" text, it is therefore not the appropriate function to use if you want binary output. For that you should use fwrite():

for (i = 0; i < sizeof(array) / sizeof(*array); i++ )
{
    fwrite (&array[i], sizeof(*array), 1, outfile ) ;
}

Note I have also fixed your loop termination to correctly iterate the number of elements in the array. But in fact the loop is unnecessary - the output is binary, the array is binary - you can just output the entire array thus:

fwrite( array, sizeof(array), 1, outfile ) ;

Your performance requirement of 50Msps will require write performance of around 95Mb/s sustained - that is a lot to ask, and unlikely to be achieved by writing one sample at a time. You may be better off using a memory mapped file, but unless you are using a real-time OS, there are no guarantees that you will sustain that output rate indefinitely - it only takes some other process to access the drive, and it may introduce an unacceptable delay.

Also note that the file must have been opened for binary output - especially on Windows to prevent translation of CR to CR+LF which will be disastrous for your sample data.

Clifford
  • 88,407
  • 13
  • 85
  • 165
1

If you want to use printf you can use something like this:

#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c\n"
#define BYTE_TO_BINARY(byte)  \
  (byte & 0x80 ? '1' : '0'), \
  (byte & 0x40 ? '1' : '0'), \
  (byte & 0x20 ? '1' : '0'), \
  (byte & 0x10 ? '1' : '0'), \
  (byte & 0x08 ? '1' : '0'), \
  (byte & 0x04 ? '1' : '0'), \
  (byte & 0x02 ? '1' : '0'), \
  (byte & 0x01 ? '1' : '0')

int main()
{
   uint8_t value = 5;  
   printf(BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(value));
   return 0;
}

Should print 00000101. I use this sometimes in embedded code when debugging to check register values. Just replace printf with fprintf if you want to write the ascii binary strings to file.

Marius
  • 380
  • 3
  • 10
  • 1
    While this may appear to be what he asked for, it seems unlikely that is what he intended given the performance requirement. It also does not result in a _binary_ file; rather a text file containing only 0x31 and 0x30 character values. – Clifford Sep 24 '18 at 17:11
0

If your compiler supports inline you don't need to worry about the overhead of a small function, take a look at this. Anyway you can simply implement the function as a macro. If you want a faster approach you can use a larger buffer (the size for the faster runtime is machine-dependent) for example char str[1 << 16], writing the results to the buffer and using fwrite/write to the out stream. Another approach is to map the process via mmap/msync. Anyway you don't need to look at a faster function, but rather a deeper knowledge of the system you're working on.

#define SHORT_WIDTH 16
#define TEST 1
#define PADDING 1 /* set to 0 if you don't need the leading 0s */

char *ShortToBin(unsigned short x, char *buffer) {
    #if PADDING
        int i;
        for(i = 0; i < SHORT_WIDTH; ++i)
            buffer[SHORT_WIDTH - i - 1] = '0' + ((x >> i) & 1);
        return buffer;
    #else
        char *ptr = buffer + SHORT_WIDTH;
        do {
            *(--ptr) = '0' + (x & 1);
            x >>= 1;
        } while(x);
        return ptr;
    #endif
}

#if TEST
    #include <stdio.h>
    
    int main() {
        short n;
        char str[SHORT_WIDTH+1]; str[SHORT_WIDTH]='\0';
        while(scanf("%hd", &n) == 1)
            puts(ShortToBin(n, str));
        return 0;   
    }
#endif