2013-08-24 96 views
0

我想写一个功能的测试仪,它需要从一个文件到另一个文件逐位写信息。我很确定我的BitOutputStream类能够工作,因为下面的代码按照预期打印出'A'。但是当我将代码更改为下面的第二个版本时,它将输入文件写入并写入输出文件,但输入与输出不匹配。我不确定是否无意中更改了我不应该的内容,或者输入文件具有导致发生不匹配或字节移位的某些“隐藏”字符。我怀疑我可能没有正确使用get()。任何帮助将不胜感激。如何将字节表单输入写入输出文件?

/*第一(工作)版本*/

int main(int argc, char* argv[]) 
{ 
    BitOutputStream bos(std::cout); // channel output to stdout 
    bos.writeBit(1); 
    bos.writeBit(0); 
    bos.writeBit(0); 
    bos.writeBit(0); 
    bos.writeBit(0); 
    bos.writeBit(0); 
    bos.writeBit(0); 
    bos.writeBit(1); 

    // prints an 'A' as expected 

    return 0; 
} 

/*第二(非工作)版本*/

int main(int argc, char* argv[]) 
{ 
    std::string ifileName = std::string(argv[1]); 
    std::string ofileName = std::string(argv[2]); 

    ofstream ofile; 
    ifstream ifile; 

    if(ifile) 
    ifile.open(ifileName, ios::binary); 
    if(ofile) 
    ofile.open(ofileName, ios::binary); 

    BitOutputStream bos(ofile); 

    int i; 
    while (ifile.good()) { 
    i = bos.writeBit(ifile.get()); // could the error be due to incorrect usage of get()? 
    std::cout << i << std::endl; // just to see how many bits have been processed 
    } 

    bos.flush(); 

    ifile.close(); 
    ofile.close(); 

    return i; 
} 

第一个版本我与

./a.out 
调用

我拨打的第二个版本

./a.out input output 

它打印向终端指示writeBit被称为3次,但我预期它被称为8次“A”,所以为什么只有3次?

输入文件中只有'A'。 输入文件调用hexdump都产生:

0000000 0a41 
0000002 

呼吁hexdump都可以对输出文件生成:

0000000 0005 
0000001 

而且为什么hexdump都产生前7份0的0A-'linefeed '和41'A',什么最后是'0000002'的意思吗?我可以在代码的第二个版本中更改什么,以便输入和输出匹配的hexdump?

编辑:这里是BitOutputStream

#ifndef BITOUTPUTSTREAM_HPP 
#define BITOUTPUTSTREAM_HPP 
#include <iostream> 

class BitOutputStream { 

private: 
    char buf;    // one byte buffer of bits 
    int nbits;   // how many bits have been written to buf 
    std::ostream& out; // reference to the output stream to use 

public: 
    /* Initialize a BitOutputStream that will 
    * use the given ostream for output. 
    * */ 
    BitOutputStream(std::ostream& os) : out(os) { 
    buf = nbits = 0; // clear buffer and bit counter 
    } 

    /* Send the buffer to the output, and clear it */ 
    void flush() { 
    out.put(buf); 
    buf = nbits = 0; 
    } 


    /* Write the least sig bit of arg into buffer */ 
    int writeBit(int i) { 
    // If bit buffer is full, flush it. 
    if (nbits == 8) 
    flush(); 

    int lb = i & 1;  // extract the lowest bit 
    buf |= lb << nbits; // shift it nbits and put in in buf 

    // increment index 
    nbits++; 

    return nbits; 
    } 
}; 

#endif // BITOUTPUTSTREAM_HPP 

回答

1

问题的声明/定义位与字节的概念。大多数功能使用的字节是位的集合。文件以字节读取。您的writeBit方法写入位而不是字节。

如果你真的真的必须以位写入,你需要读取字节,转换为位并写入每一位。 (顺便说一下,大多数计算机具有较大的单位更好的工作,如字节,和字。)

#include <cstdint> 
#include <iostream> 

using namespace std; // Because I'm lazy and this is an example. 

int main(void) 
{ 
    uint8_t byte; 
// Open the file 
//.... 

// Read file as bytes. 
    while (ifile.read(&byte, sizeof(byte))) 
    { 
     for (unsigned int i = 0; 
      i < CHAR_BIT; // number of bits in a byte 
      ++i) 
     { 
      bos.writeBit(byte & 1); 
      byte = byte >> 1; 
     } 
    } 
//... 
    return EXIT_SUCCESS; 
} 

有更快的方式,以一个文件的内容复制到另一个。首先想到的是让操作系统去做。

编辑1:程序分析。
BitOutputStream类将累加传递给writeBit方法的整数的最低有效位。一旦累积了8位,writeBit方法就会向输出流写入一个字节。

在第一个程序,你逝去的是只有一个显著位整数,或者你假设整型常量只有一个显著位。

在第二程序,则在一个字节(8位),通过istream::get()方法读取。 writeBit方法只查找最低有效位并将该位放入BitOutputStream缓冲区。循环然后从输入文件中提取另一个字节,并且只有最低有效位被附加到BitOutputStream缓冲区。

第8字节被读出之后,BitOutputStream缓冲器将有8位,然后一个8位字节被写入到流中。

所以,如果我有一个唯一的“A”字符的文件,这是0×41,或二进制MSB:0100 0001
writeBit方法与运算与为0x1的值,与为0x01的结果或二进制1该位被放入输出缓冲区。 该字节的剩余位被忽略writeBit

只有1个字符时,BitOutputStream缓冲区只有1位。另外,你的程序永远不会调用BitOutputStream::flush(),所以部分位永远不会输出到流中。没有析构函数,因此当bos对象被销毁并且没有写入输出流时,不完整的字节(只有1位)消失。

因为你的第二个程序通过8位到只使用1位的函数整个字节,我推断你混淆了比特和字节的概念。看到我的上面的代码片段,解决您的问题。

编辑2:测试BitOutputStream类。
测试此类的最佳过程是从ostream派生自己的类。这个类应该有一个方法,你可以通过一个预期的已知的值来。将此类的实例传递给BitOutputStream。类的put方法能值比较来自BitOutputStream预期值。

+0

我明白一个位和一个字节之间的差异,我的第一句话应该说“一点一点”,而不是我编辑的“逐字节”。我的类BitOutputStream完全按照你所描述的 - 读取字节,将它们转换为位并写入每一位,这正是我想要的。但是在编写测​​试程序时,我的输入和输出文件不匹配,我想知道为什么。 – Napalidon

+0

如果您逐字节复制,您也一点一点地复制,除非我遗漏了一些概念。 –

+1

没有看到BitOutputStream的声明和定义,我不能给你任何更详细的帮助。 –