LoginSignup
13
11

More than 3 years have passed since last update.

C++でバイナリ形式で入出力してみた

Posted at

バイナリとは

2進数のこと。
コンピュータが処理・記憶するために2進化されたファイルまたはその内部表現の形式のこと等を指します。

画像ファイルを読み込んでみた

今回は以下の画像ファイルを読んで、バイナリデータで出力してみます。
test.png

メインプロセス
#include <string>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    string fileName;    //ファイル名

    //キーボード入力からファイル名を取得する
    getline(cin, fileName);

    //ファイル名からバイナリファイルで読み込む
    std::ifstream ifs(fileName, std::ios::binary);

    //読込サイズを調べる。
    ifs.seekg(0, std::ios::end);
    long long int size = ifs.tellg();
    ifs.seekg(0);

    //読み込んだデータをchar型に出力する
    char *data = new char[size];
    ifs.read(data, size);

    //サイズを出力する
    std::cout << "size = " << size << "\n";
    for (int i = 1; i < size + 1; i++)
    {
        //出力する
        std::cout <<data[i - 1] << " ";
        //16バイト毎に改行する
        if ((i % 16) == 0)
        {
            std::cout << "\n";
        }
    }
    std::cout << "\nEnd!\n";
    delete data;
    return 0;
}

読み込んだ結果が以下になります。
バイナリ読込結果.PNG

正しく読み込めているのかわからないので、フリーソフトを使って確認してみます。
Stirlingを使って確認してみます。
Stirlingの結果が以下になります。
バイナリ読込結果_stirling.PNG

正しく読込が出来ていそうですが、ASCIIコードで変換できない値が
正しく読み込めているか確認できません。
ASCIIコードで「0A」がある箇所が改行されていそうです。

ASCII文字から16進数に変えてみた

プログラムを以下のように変えて、ASCIIから16進数で出力してみます。

メインプロセス
#include <string>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <fstream>

using namespace std;

int main()
{
    string fileName;    //ファイル名

    //キーボード入力からファイル名を取得する
    getline(cin, fileName);

    //ファイル名からバイナリファイルで読み込む
    std::ifstream ifs(fileName, std::ios::binary);

    //読込サイズを調べる。
    ifs.seekg(0, std::ios::end);
    long long int size = ifs.tellg();
    ifs.seekg(0);

    //読み込んだデータをchar型に出力する
    char *data = new char[size];
    ifs.read(data, size);

    //サイズを出力する
    std::cout << "size = "<< size <<"\n" ;
    for (int i = 1; i < size + 1; i++)
    {
        std::stringstream ss;
        /*16進数文字列に変換する
         char型をASCIIではなく、数値で出力する場合は先頭に+を付ける*/
        ss << std::hex << +data[i - 1];

        string test = ss.str();
        //符号付きであるか判定する
        if (test.size() > 5)
        {
            //符号付きの場合fが付くため、fを削除する
            string test = ss.str().erase(0, 6);
            std::cout << test << " ";
        }
        else
        {
            //符号付きでない場合そのまま出力する
            std::cout << ss.str() << " ";
        }
        //16バイト毎に改行する
        if ((i % 16) == 0)
        {
            std::cout << "\n";
        }
    }
    std::cout << "\nEnd!\n"; 
    delete data;
    return 0;
}

ASCII文字に変えた結果が以下になります。
バイナリ読込結果(16進数).PNG

Stirlingの結果と比較しても正しく値が読み込めてることが確認できます。

終わりに

C++でバイナリデータを確認することが出来ました。
ただし、newで領域を確保したため巨大なデータには対応できなさそうです。

13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11