2013-08-24 152 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的聲明和定義,我不能給你任何更詳細的幫助。 –