1

我正在尝试创建一个压缩程序,但我需要了解如何打开二进制文件并打印出其内容的基础知识。

在一个名为“Tester.txt”的文本文件中,我有这个:

乔丹

在 .cpp 文件中,我有这个:

#include <fstream>
#include <iostream>
#include <string>

using namespace std;
int main
{ 
    fstream istr;
    istr.open("Tester.txt", ios::binary);      
}

根据我在 cplusplus 参考中的理解,这使用流对象打开以二进制指定的文件?

但我被困在如何准确地“打印”出文件的第一个字节,即二进制中的字母 M?

我知道二进制中的 M(大写字母)是 01001101。

那么我如何在二进制中计算 M 呢?

谢谢

4

5 回答 5

3

您在数字和数字表示之间存在混淆,这可能是由于“二进制”一词有时可以用来描述两者而造成的。当您以“二进制模式”打开文件时,这意味着您会看到文件中字节的原始值。在以二为基数表示数字的意义上,这与“二进制”无关。

假设文件有“x”,后跟换行符和回车符。在“二进制模式”中,您将看到三个字节大小的值,一个包含“x”的 ASCII 代码,一个包含换行符的 ASCII 代码,一个包含返回的 ASCII 代码。这些是您从文件中读取的值。可以用二进制表示它们,但也可以用十进制或十六进制表示它们,您仍然从文件中读取了完全相同的

以“二进制”格式读取文件决定了您读取的,而不是您如何表示它们。无论您将值2表示为“2”(十进制)、“10”(二进制)还是“two”(英文),两辆车都是相同的两辆车。

于 2013-05-11T18:54:38.413 回答
2

流上的二进制输入/输出是使用它们的成员函数read()write().

像这样:

#include <fstream>
#include <iostream>
#include <string>

using namespace std;
int main
{ 
    fstream istr;
    istr.open("Tester.txt", ios::binary);
    if (istr) {
      // Read one byte
      char byte;
      if (!istr.read(&byte, 1)) {
        // Error when reading
      }
      // Alternative way to read one byte (thanks to DyP)
      byte = istr.get();
      // Another alternative:
      if (!istr.get(byte)) {
        // Error when reading.
      }
      // Read a block of bytes:
      char buffer[1024];
      if (!istr.read(buffer, 1024)) {
        // Read error, or EOF reached before 1024 bytes were read.
      }
    }
}
于 2013-05-11T18:41:03.280 回答
1

要以二进制形式输出值,您需要手动执行,因为标准库不支持该输出格式。

int mask = 0x80;
while(mask)
{
    std::cout << (byteValue & mask ? '1' : '0');
    mask >>= 1;
}
std::cout << std::endl;

这将从高位扫描到低位并打印出代表每个位的值。

于 2013-05-11T18:46:46.267 回答
1

这是一个使用 C++ 标准库完成所有繁重工作的快速程序。

#include <iostream>
#include <iterator>
#include <bitset>
#include <algorithm>

int main() {
    std::istreambuf_iterator< char > in( std::cin ), in_end;
    std::ostream_iterator< std::bitset< 8 > > out( std::cout, " " );
    std::copy( in, in_end, out );
    std::cout << '\n';
}

看它运行。我用于std::cin演示,但你应该打开一个文件std::ios::binary并传递它。

由于每个变量只使用一次,因此这一切都可以在一行中完成。即使您打开文件而不是使用std::cin.


编辑:

  • std::copy是一个封装循环的函数for ( ; in != in_end; ++ in ) * out ++ = * in;
  • 该类型std::istreambuf_iterator要么接受istream构造函数参数并提供in适合此类循环的迭代器,要么不接受构造函数参数并提供迭代器in_end,例如in == in_endif in.eof() == truechar迭代器从流中获取未格式化的字节(类型)。
  • 该类型std::ostream_iterator< std::bitset< 8 > >提供了一个迭代器out,因此* out ++ = x可以转换xstd::bitset< 8 >打印结果。在这种情况下x是一个字节并bitset为这样的字节值提供构造函数,并重载operator<<以打印 1 和 0 的二进制表示。
于 2013-05-12T02:06:28.930 回答
0

尝试这个:

#include <fstream>
#include <iostream>
#include <string>
#include <bitset>
#include <iomanip>


int main()
{ 
    // Set up your objects.
    char          c;
    std::fstream  istr("Tester.txt", ios::binary);  
    unsigned long loc = 0;

    // Read the file one character at a time.
    // Remembering not to skip white space in this situation.
    for(;istr >> std::noskipws >> c;++loc)
    {
        // When printing compensate for non printable characters.
        // If the character is outside the ASCII range then print it as an integer.
        std::stringstream  charStr;
        if ((c < 32) || (c > 126))
        {
            charStr << "Char: " << c;
        }
        else
        {
            charStr << "Non Printable: " << static_cast<int>(c);
        }

        // Print the value and location in a nicely formatted way.
        std::cout << std::setw(16) << location 
                  << " : " 
                  << std::bitset<8>(c).to_string()  // Prints the character as an 8 bit binary value.
                  << " : "
                  << charStr.str()
                  << "\n";
    }
}

但是已经有标准工具可以做到这一点:

看着od

于 2013-05-11T20:07:58.087 回答