What are the fastest data encoding and decoding methods? Can we use shifting to encode or decode data or files? How can we make use of the C++ compiler? Can we use shifting on strings or binary data? Should we? We’ll do our best to answer all of these questions.
Bits and bitwise operations
The bit is the most basic unit of information in computing and digital communications. In real all operators are mainly based on Bit Operations which are also called Bitwise Operations. In computer programming, a Bitwise Operation operates on a bit string, a bit array, or a binary numeral (considered as a bit string) at the level of its individual bits, 1s, and 0s. The Bitwise Operation is basic to the higher-level arithmetic operations and it is a fast and simple action because it is directly supported by the processors. Most bitwise operations are presented as two-operand instructions where the result replaces one of the input operands.
Because of all these basics of the microarchitecture of computers, it is very important to know Bitwise Operators. C Programming language is one of the oldest programming languages and a lot of operands, operators in other programming languages got inspiration from this language. C and C++ have the same operators and most of them are the same in other programming languages. We have explained well about operators in general in this Learn How To Use Operators In C++ post before. Now let’s see Bit Shifting and Encoding – Decoding examples.
Bit Shifting Data
One of the Bitwise Operand is the Bit Shifting, the Left Shifting with ‘<<‘ operand, and the Right Shifting ‘>>‘ operand. Bit operations are the fastest operations in machine codes and in C++ because of the microarchitecture of computers as explained above. There are many encoding and decoding methods, also hash coding methods. One of the easiest and the fastest encoding method is Bit Shifting Data. We can use this method to encode and decode data files.
Left Shifting and Right Shifting
For example if c is char we can encode and decode this char by using bit shifting as below,
1 2 3 4 |
c = c << 1; // Encoding with Left Bit Shifting c = c >> 1; // Decoding with Right Bit Shifting |
This works well in lower than 127 char numbers. When shifting we lost the frontier bits (when shifting left we lost left bit or bits and when shifting right we lost right bit or bits). To hold all these bits in a binary data we should do Circular Bit Shifting,
Circular Left Shifting and Circular Right Shifting
If we use Circular Bit Shifting, we never loose any bits when we encode or decode our data. If we want to shift 2 bits from maximum of 8 bits we can do left and right circular bit shifting as below,
1 2 3 4 |
c =(c << 2)|(c >> (8 - 2); // Encoding with Circular Left 2 Bits Shifting c =(c >> 2)|(c << (8 - 2); // Decoding with Circular Right 2 Bits Shifting |
Circular Left Shifting and Circular Right Shifting with Complexity
We can add complexity to number of shifting bits by adding (1+i%7) for example,
1 2 3 4 |
c =(c << (1+i%7))|(c >> (8 - (1+i%7)); // Encoding by Circular Left Bits Shifting with Complexity c =(c >> (1+i%7))|(c << (8 - (1+i%7)); // Decoding by Circular Right Bits Shifting with Complexity |
Also, we have the C++ bit set ready to help you increase productivity in programming with its modern features.
Bit Shifting Data Files in C++ Builder
For example we can use this Circular Bit Shifting Method with Complexity to Encode and Decode data files in C++ Builder. To do this example in C++ Builder,
- Create a new C++ Builder VCL Project and save all files to a project folder
- Add 2 Buttons (TButton), set Button1->Caption = “Encode” and Button2->Caption = “Decode”
- Add a Memo (TMemo) and OpenDialog (TOpenDialog) component on to form by dragging it from the Palette
- Press F12 to switch to code mode and add these headers to your codes as in given example below,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//--------------------------------------------------------------------------- #include <vcl.h> #include <iostream> #include <fstream> #include <string> #pragma hdrstop #include "Encoding_and_Decoding_Data_File_VCL_Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } |
5. Double Click to Button1 ‘Encode’ button and add these lines below to open, encode and save encoded file,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { // ENCODING OpenDialog1->Title = "Choose a File to Encode"; OpenDialog1->DefaultExt = ""; OpenDialog1->FileName = ""; OpenDialog1->Execute(); if(OpenDialog1->FileName.Length()>0) { unsigned char c; // std::bitset<8> x; unsigned int i=0; std::ifstream indata; std::ofstream outdata; indata.open(OpenDialog1->FileName.w_str(), std::fstream::binary); if(!indata) { Memo1->Lines->Add("Error: Input file could not be opened"); exit(1); } outdata.open((OpenDialog1->FileName+".enc").w_str(), std::fstream::binary); if(!outdata) { Memo1->Lines->Add("Error: Output file could not be openedn"); indata.close(); exit(1); } Memo1->Lines->Add("nEncoding..n"); i=0; while ( !indata.eof() ) { c=indata.get(); // get the next char of data or indata.get(); c =(c << (1+i%7))|(c >> (8 - (1+i%7))); // Encoding by Circular Left Bit Shifting with Complexity outdata.put(c); // out the encoded char i++; } indata.close(); outdata.close(); Memo1->Lines->Add("Done! '"+OpenDialog1->FileName+".enc' saved!"); } } |
6. Double click to Button2 ‘Decode’ button and add these lines below to open encoded file, decode and save decoded file,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
//--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { OpenDialog1->Title = "Choose .enc File to Decode"; OpenDialog1->DefaultExt = ""; OpenDialog1->FileName ="*.enc"; OpenDialog1->Execute(); if(OpenDialog1->FileName.Length()>0) { unsigned char c; // std::bitset<8> x; unsigned int i=0; std::ifstream indata; std::ofstream outdata; // DECODING mytest.dat to mytest2.txt // --------------------------------------------------------- indata.open(OpenDialog1->FileName.w_str(), std::fstream::binary); if(!indata) { Memo1->Lines->Add("Error: Input file could not be opened"); exit(1); } outdata.open((OpenDialog1->FileName+".dec").w_str(), std::fstream::binary); if(!outdata) { Memo1->Lines->Add("Error: Output file could not be openedn"); indata.close(); exit(1); } i=0; Memo1->Lines->Add("nDecoding..n"); while ( !indata.eof() ) { c= indata.get(); // get the next char of data //c = c >> 1; // Decoding with Right Bit Shifting c =(c >> (1+i%7))|(c << (8 - (1+i%7))); // Decoding by Right Bit Shifting with Complexity outdata.put(c); // out the encoded char i++; } indata.close(); outdata.close(); Memo1->Lines->Add("Done! '"+OpenDialog1->FileName+".dec' saved!"); } } |
7. Press F9 to compile and run with debugging. Now you can choose a file to encode and encode the *.enc file to decode as *.dec file
We could use this bit shifting method to protect our data, user names, passwords and similar sensitive items as a fun exercise but bit shifting in this way is a form of security through obscurity. There are industry standard security practices such as salting passwords and using industry standard encryption that provide real security.
Industry standard practices like salting passwords should use powerful cryptographic hash functions such as ones available in modern C++ on Windows (SHA, SHA2, MD5, BobJenkins, etc.). See this Learn To Use Powerful Cryptographic Hash Functions In Modern C++ On Windows (SHA, SHA2, MD5, BobJenkins). Libraries such as IPWorks Encrypt 2020 are available via Embarcadero’s GetIt and offer strong industry standard encryption.
Learn more about techniques how you can tackle common questions on Strings in C++ in this informative article.
RAD Studio C++ Builder is a great environment for learning to use C++ and is also powerful enough for all your development needs. Why not download and try C++ builder today?
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition