ifstream extraction operator not working - c++

I'm trying to read data from binary file using folloing code:
fstream s;
s.open(L"E:\\test_bin.bin", ios::in | ios::binary);
int c = 0;
while (!s.eof())
{
s >> c;
cout << c;
}
c is always 0 (current value of c. If I set c to 1, result is 1). File exists and it has data that is not zeros, so problem is not at file. I can read this file using fread and using s.get(), but why given code not working?

Using the ios::binary flag doesn't necessarily mean that you read and write binary data. Take a look at https://stackoverflow.com/a/2225612/2372604 . ios::binary means "data is read or written without translating..."
What you probably want to do is use s.read(...). In your case the stream operator attempt to read a complete integer (something like "1234") rather then X number of bits that will fit into your integer.
For reading 4 bytes, something like the folling might work (untested):
int n;
while (s.read((char*) &n, 4) && s.gcount() != 0 ) {}

What's wrong with:
int c = 0;
char ch;
int shift = 32;
while ( s.get( ch ) && shift != 0 ) {
shift -= 8;
c |= (ch & 0xFF) << shift;
}
if ( shift != 0 ) {
// Unexpected end of file...
}
This is the (more or less) standard way of reading binary 32 bit
integers off the network. (This supposes that native int is
32 bits 2's complement, of course.)
Some protocols use different representation of 32 bit ints, and
so will require different code.
As for your original code: the test s.eof() is always wrong,
and >> is for inputting text; in particular, it will skip
leading whitespace (and binary data may contain codes which
correspond to whitespace).
I might also add that you should ensure that the stream is
imbued with the "C" locale, so that no code translation
occurs.

Related

How to write single bits into bin file

i am trying to make an compress program that for example write instead regular 8 bits (char) only 1 or 2 bits, depend of the char we are trying to write. i tried to write with:
//I dont know what the function should return
char getBytes(char c)
{
return 0xff;
}
ofstream fout;
fout.open("file.bin", ios::binary | ios::out);
fout << getBytes(c);
but so far i succed writing only chars.
so how can i write for example: '01'? or only '1'? in what function i should use for write into file with only bytes? thanks.
Streams are sequences of bytes. There is no standard interface to write individual bits. If you want to write individual bits you’ll need to create your own abstraction of a bit stream built on top of streams. It would aggregate multiple bits into a byte which is then written to the underlying stream. If you want reasonable efficient writing you’ll probably need to aggregate multiple bytes before writing them to the stream.
A naïve implementation could look something like this:
class bitstream {
std::streambuf* sbuf;
int count = 0;
unsigned char byte = 0;
public:
bitstream(std::ostream& out): sbuf(out.rdbuf()) {}
~bitstream() {
if (this->count) {
this->sbuf->sputc(this->byte);
}
}
bitstream& operator<< (bool b) {
this->byte = (this->byte << 1) | b;
if (++this->count == 8) {
this->sbuf->sputc(this->byte);
this->count = 0;
}
return *this;
}
};
Note that this implementation has rather basic handling for the last byte: if a byte was started it will be written as is. Whether that is the intended behavior or whether it needs to be shifted for the written bits being in the top bits of the last byte depends on how things are being used. Also, there is no error handling for the case that the underlying stream couldn’t be written. (and the code is untest - I don’t have an easy way to compile on my mobile phone)
You’d use the class something like this:
int main() {
std::ofstream file(“bits.txt”, std::ios_base::binary);
bitstream out(file);
out << false << true << false << false
<< false << false << false << true;
}
Unless I messed things up, the above code should write A into the file bits.txt (the ASCII code for A is 65).
Just for context: files are actually organized into blocks of bytes. However, the stream abstraction aggregates the individual bytes written into blocks. Although byte oriented interfaces are provided by all popular operating systems writing anything but blocks of data tends to be rather inefficient.

how to copy binary data of a file

Basically, I am trying to read binary data of a file by using fread() and print it on screen using printf(), now, the problem is that when it prints it out, it actually don't show it as binary 1 and 0 but printing symbols and stuff which I don't know what they are.
This is how I am doing it:
#include <stdio.h>
#include <windows.h>
int main(){
size_t sizeForB, sizeForT;
char ForBinary[BUFSIZ], ForText[BUFSIZ];
char RFB [] = "C:\\users\\(Unknown)\\Desktop\\hi.mp4" ; // Step 1
FILE *ReadBFrom = fopen(RFB , "rb" );
if(ReadBFrom == NULL){
printf("Following File were Not found: %s", RFB);
return -1;
} else {
printf("Following File were found: %s\n", RFB); // Step 2
while(sizeForB = fread(ForBinary, 1, BUFSIZ, ReadBFrom)){ // Step 1
printf("%s", ForBinary);
}
fclose(ReadBFrom);
}
return 0;
}
I would really appreciate if someone could help me out to read the actual binary data of a file as binary (0,1).
while(sizeForB = fread(ForBinary, 1, BUFSIZ, ReadBFrom)){
printf("%s", ForBinary); }
This is wrong on many levels. First of all you said it is binary file - which means there might not be text in it in the first place, and you are using %s format specifier which is used to print null terminated strings. Again since this is binary file, and there might not be text in it in the first place, %s is the wrong format specifier to use. And even if there was text inside this file, you are not sure that fread would read a "complete" null terminated string that you could pass to printf with format specifier %s.
What you may want to do is, read each byte form a file, convert it to a binary representation (google how to convert integer to binary string say, e.g., here), and print binary representation for each that byte.
Basically pseudocode:
foreach (byte b in FileContents)
{
string s = convertToBinary(b);
println(s);
}
How to view files in binary in the terminal?
Either
"hexdump -C yourfile.bin" perhaps, unless you want to edit it of course. Most linux distros have hexdump by default (but obviously not all).
or
xxd -b file
To simply read a file and print it in binary (ones and zeros), read it one char at a time. Then for each bit, print a '0' or '1'. Can print Most or Least significant bit first. Suggest MSb.
if (ReadBFrom) {
int ch;
while ((ch = fgetc(ReadBFrom)) != EOF) {
unsigned mask = 1u << (CHAR_BIT - 1); // CHAR_BIT is typically 8
while (mask) {
putchar(mask & ch ? '1' : '0');
mask >>= 1;
}
}
fclose(ReadBFrom);
}

writing bits into a c++ file

I'm working on Huffman coding and I have built the chars frequency table with a
std::map<char,int> frequencyTable;
Then I have built the Huffman tree and then i have built the codes table in this way:
std::map<char,std::vector<bool> > codes;
Now I would read the input file, character by character ,and encode them through the codes table but i don't know how write bits into a binary output file.
Any advice?
UPDATE:
Now i'm trying with these functions:
void Encoder::makeFile()
{
char c,ch;
unsigned char ch2;
while(inFile.get(c))
{
ch=c;
//send the Huffman string to output file bit by bit
for(unsigned int i=0;i < codes[ch].size();++i)
{
if(codes[ch].at(i)==false){
ch2=0;
}else{
ch2=1;
}
encode(ch2, outFile);
}
}
ch2=2; // send EOF
encode(ch2, outFile);
inFile.close();
outFile.close();
}
and this:
void Encoder::encode(unsigned char i, std::ofstream & outFile)
{
int bit_pos=0; //0 to 7 (left to right) on the byte block
unsigned char c; //byte block to write
if(i<2) //if not EOF
{
if(i==1)
c |= (i<<(7-bit_pos)); //add a 1 to the byte
else //i==0
c=c & static_cast<unsigned char>(255-(1<<(7-bit_pos))); //add a 0
++bit_pos;
bit_pos%=8;
if(bit_pos==0)
{
outFile.put(c);
c='\0';
}
}
else
{
outFile.put(c);
}
}
but ,I don't know why ,it doesn't work, the loop is never executed and the encode function is never used, why?
You can't write a single bit directly to a file. The I/O unit of reading/writing is a byte (8-bits). So you need to pack your bools into chunks of 8 bits and then write the bytes. See Writing files in bit form to a file in C or How to write single bits to a file in C for example.
The C++ Standard streams support an access of the smallest unit the underlying CPU supports. That's a byte.
There are implementation of a bit stream class in C++ like the
Stanford Bitstream Class.
Another approach could use the std::bitset class.

Need to change a string to binary, then to ASCII

I have some data coming in from a sensor. The data is in the range of a signed int, 16 bits or so. I need to send the data out via Bluetooth.
Problem:
The data is -1564, lets say.The Bluetooth transmits -, 1, 5, 6, then 4. This is inefficient. I can process the data on the PC later, I just need the frequency to go up.
My Idea/ Solution:
Have it convert to binary, then to ASCII for output. I can convert the ASCII later in processing. I have the binary part (found on StackOverflow) here:
inline void printbincharpad(char c)
{
for (int i = 7; i >= 0; --i)
{
putchar( (c & (1 << i)) ? '1' : '0' );
}
}
This outputs in binary very well. But getting the bluetooth to transmit, say 24, spits out 1, 1, 0, 0, then 0. In fact, slower than just 2, then 4.
Say I have 65062, 5 bytes to transmit, coming out of the sensor. That is 1111111000100110 in binary, 16 bytes. To ASCII, it's �& (yes, the character set here is small, I know, but it's unique) just 2 bytes! In HEX it's FE26, 4 bytes. A savings of 3 vs decimal and 14 vs. binary and 2 vs. Hex. Ok, obviously, I want ASCII sent out here.
My Question:
So, how do I convert to ASCII if given a binary input?
I want to send that, the ASCII
Hedging:
Yes, I code in MatLab more than C++. This is for a microcontroller. The BAUD is 115200. No, I don't know how the above code works, I don't know where putchar's documentation is found. If you knw of a library that I need to run this, please tell me, as I do not know.
Thank you for any and all help or advice, I do appreciate it.
EDIT: In response to some of the comments: it's two 16 bit registers I am reading from, so data loss is impossible.
putchar writes to the standard output, which is usually the console.
You may take a look at the other output functions in the cstdio (or stdio.h) library.
Anyways, using putchar(), here's one way to achieve what you're asking for:
void print_bytes (int n)
{
char *p = (char *) &n ;
for (size_t i = 0; i < sizeof (n); ++i) {
putchar (p [i]) ;
}
}
If you know for certain that you only want 16 bits from the integer, you can simplify this like this:
void print_bytes (int n)
{
char b = n & 0xff ;
char a = (n >> 8) & 0xff ;
putchar (a) ;
putchar (b) ;
}
Looks like when you say ASCII, you mean Base 256. You can search for solutions to converting from Base 10 to Base 256.
Here is a C program that converts an string containing 65062 (5 characters) to a string of 2 characters:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* inputString="65062";
int input;
char* tmpString;
char* outString;
int Counter;
input = atoi(inputString);
outString= malloc (sizeof(input) + 1);
tmpString = &input;
for (Counter=0; Counter < sizeof(input) ; Counter++) {
outString[Counter] = tmpString[Counter];
}
outString[sizeof(input)] = '\0';
printf ("outString = %s\n", outString);
free(outString);
}

Reading Unicode characters from a file in C++

I want to read Unicode file (UTF-8) character by character, but I don't know how to read from a file one by one character.
Can anyone to tell me how to do that?
First, look at how UTF-8 encodes characters: http://en.wikipedia.org/wiki/UTF-8#Description
Each Unicode character is encoded to one or more UTF-8 byte. After you read first next byte in the file, according to that table:
(Row 1) If the most significant bit is 0 (char & 0x80 == 0) you have your character.
(Row 2) If the three most significant bits are 110 (char & 0xE0 == 0xc0), you have to read another byte, and the bits 4,3,2 of the first UTF-8 byte (110YYYyy) make the first byte of the Unicode character (00000YYY) and the two least significant bits with 6 least significant bits of the next byte (10xxxxxx) make the second byte of the Unicode character (yyxxxxxx); You can do the bit arithmetic using shifts and logical operators of C/C++ easily:
UnicodeByte1 = (UTF8Byte1 << 3) & 0xE0;
UnicodeByte2 = ( (UTF8Byte1 << 6) & 0xC0 ) | (UTF8Byte2 & 0x3F);
And so on...
Sounds a bit complicated, but it's not difficult if you know how to modify the bits to put them in proper place to decode a UTF-8 string.
UTF-8 is ASCII compatible, so you can read a UTF-8 file like you would an ASCII file. The C++ way to read a whole file into a string is:
#include <iostream>
#include <string>
#include <fstream>
std::ifstream fs("my_file.txt");
std::string content((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
The resultant string has characters corresponding to UTF-8 bytes. you could loop through it like so:
for (std::string::iterator i = content.begin(); i != content.end(); ++i) {
char nextChar = *i;
// do stuff here.
}
Alternatively, you could open the file in binary mode, and then move through each byte that way:
std::ifstream fs("my_file.txt", std::ifstream::binary);
if (fs.is_open()) {
char nextChar;
while (fs.good()) {
fs >> nextChar;
// do stuff here.
}
}
If you want to do more complicated things, I suggest you take a peek at Qt. I've found it rather useful for this sort of stuff. At least, less painful than ICU, for doing largely practical things.
QFile file;
if (file.open("my_file.text") {
QTextStream in(&file);
in.setCodec("UTF-8")
QString contents = in.readAll();
return;
}
In theory strlib.h has a function mblen which shell return length of multibyte symbol. But in my case it returns -1 for first byte of multibyte symbol and continue it returns all time. So I write the following:
{
if(i_ch == nullptr) return -1;
int l = 0;
char ch = *i_ch;
int mask = 0x80;
while(ch & mask) {
l++;
mask = (mask >> 1);
}
if (l < 4) return -1;
return l;
}
It's take less time than research how shell using mblen.
try this: get the file and then loop through the text based on it's length
Pseudocode:
String s = file.toString();
int len = s.length();
for(int i=0; i < len; i++)
{
String the_character = s[i].
// TODO : Do your thing :o)
}