Marshall Cocop
Marshall Cocop

Reputation: 161

C - Cannot read all characters when reading a file

I am currently working on a lossless compression algorithm using the Huffman technique. I managed to compress the desired file, and save the compressed data to a file. However, I am unable to correctly read what is recorded in this file. Preferably, I would like to store the contents of this file in a std::string.

Here is the content of this file:

00000L,1LP10LURD100LVRj1LLRQRER.Rm1LlRr1LiRe1000LpRdRn100Lv100LC1LARF1LIRNRbRcRa100Lo100Lh1Lx1LMRSRf1LgRqRs1LuRt

X6*ÃWØ¿¸u÷üwµS™’ð‚<)âóUO_mÁ9Õö/ë‰ÍÌ Ï-,SÁúÚâuçëðÒì`WVwÿƒüšÎ뉊?Âgÿ­PÞuâ[CßTø¸CJŸy™“Þ¸Ý{+1sü <Ï~÷øà·\@¾¯à禡ú±Õö/Þüºû"í+ª•tÊæ+Ó¸Ð÷Õ>.'¦º¾Åü
úá‡
lÀ•¥¸Äq/?03òØ2'>÷?>9»ŸtY®Ùyù„‰u®'^~¿Û‚sŸ–öŽ(wß°/ì–~+K*•O´ ÿV:âyšö¨oãúü:ÿhrkã[‹7çjëĶ†KßW›˜iSêj£ÓúÆÉ×ûoÆÉï\l ÜKª‘Úɬ®b]T«ÏÖ42+4­Ô2µ“í«Ç7•’Ðä×Æ·Ø÷+ìÊþ¸˜¡sü!xSC—7ëoÿø=_bÿÔÕG§ÃIöÕÐÊV¥:ÅÅ?]Yß„ËsòÖx×™øÞíàæÍÓ+˜¯~7Æ´ 
puQäöÕA}ÿ².Õ {vÓ+˜¯¾ÍÌ ŽÞ¹úb+
 ç·ñd³óÿSUŸ
/ˆ®Œ|/õ}‹ñT`»áúüi|EuÄæçMSs’âóUOrßUSí
 ïFòH{Tû8ð¹C«ì_ׯ?_†—ÄWÅæªöV’ŽÜc`>ö0Á‹þÚ8¡ß~ÃH;ÜÙ¸dY¿;þ8-\`ÈœûÜüÞþSS™Zäî#d÷®7Bûo}åʪ¿ŽŽ(wß°Òö?õø0¡¿¾¯àÕ׉hñÇ7·™­Û‚rþ[ª%«KÅ’ý_býCxBí럿‡
löàœ„õÄææ÷îªÃÜ0ëðaxSˆ¬C´êÿm¨³]¯À¦W1^§T_XË®â6OF÷l4Ž;¦¿æ{÷»y—úØ«äý°sºâ³JÝB7ƶ…öñ«&ksóâóUOB    ‘9÷¹ùÅf•º†ë^¹,«Ì÷ïCIÏÖ0Áÿ¯Á¿žšç壂{é„Eë"í¡–VK{åSÈ-Êjs"+
*}œx_“Þ¸Þ[·[ŸjÃBµN[êª}¡}’ÏÖ4<…^+PÞ‡16kø¼Õ^‡&ÁÓO.UUülñªY/dÅÏð€þ7O·?X×.„4Ÿm]2¹Š÷’œO©ªOúš¨ôøiSìãÂülžõÆòؽºÜûPÞªrßUSí?Õ~lÜ­@_ÿ­%›ŠÃIÏÖ,ïèÁwÂü4©¯ö¨oéZÁœSøªÿA¸—XõÂòO$Ìþ¸Äq>Ú¹¿[ÞY¬‹µòÑÄrÄÙ¯r†…öáæl ™Ÿ{Ÿ›&²¹Œº‹þÙÄíæ_ëBõb}çÃb8"ZW^Òº©Vɬ®bp¨±í¿Ê¥Sí³¯pȳ~vÎü ï–çç\LP¹þÛBûpÆó7\LP¹þ‚<)dÖW1d¾ë싶‹5Ûo3

Here is the code I wrote to read its contents:

int main(){     
    int number_of_lines = 0;
    std::string line;
    
    std::ifstream myfile("my_file.txt.huff");
    while (std::getline(myfile, line)){
        ++number_of_lines;;
        std::cout << "line number: " << number_of_lines << " content: " << line << std::endl;
    }
}

I also tried via this way:

int main(){     
    FILE *find = fopen("my_file.txt.huff", "r");
    int ca;
    while(EOF != (ca=fgetc(find)))
          std::cout << (char)ca;
    std::cout << std::endl;
}

Here is the console rendering for the first code given:

line number : 1 content : 00000L,1LP10LURD100LVRj1LLRQRER.Rm1LlRr1LiRe1000LpRdRn100Lv100LC1LARF1LIRNRbRcRa100Lo100Lh1Lx1LMRSRf1LgRqRs1LuRt
line number : 2 content :
line number : 3 content : X6*├WÏ┐©Øu¸³wÁSÖÆ­é<)Ô¾UO_m┴9ı÷/Ùë═╠ ¤-,S┴·┌ÔuþÙ­Êý`WVw â³

At every time I try to read this file the problem is repeated. Indeed, the methods I use do not allow me to read it entirely.

Why does this problem occur?

thank you in advance

N.B: I was able to test, without success, the solution provided by Cillié Malan in this post. I'm having trouble for converting from a std::wstringstream to a std::string correctly.

Upvotes: 0

Views: 473

Answers (1)

David C. Rankin
David C. Rankin

Reputation: 84521

Here is a short example that opens the file in binary mode and reads the entire file into a std::vector<uint8_t>. (you can also use a std::array<uint8_t> if you like). You open the file, .seekg() to the end, get the number of bytes and create the vector with that number of bytes and then .read() the file into the vector.

The following takes the filename as the first argument and outputs the content in hex format (for large files, change the output before testing to limit what is dumped to stdout)

#include <iostream>
#include <fstream>
#include <vector>

int main (int argc, char **argv) {

    if (argc < 2) { /* validate filename given as argument */
        std::cerr << "error: insufficient arguments\n"
                    "usage: " << argv[0] << " filename.bin\n";
        return 1;
    }
    /* open file in binary mode, position at-the-end */
    std::ifstream f (argv[1], std::ios::binary | std::ios::ate);

    if (!f.is_open())                           /* validate file open for reading */
        return 1;
    
    size_t nbytes = f.tellg();                  /* get number of bytes in file */
    f.seekg (0);                                /* rewind */
    
    std::vector<uint8_t> arr(nbytes);           /* declare vector with adequate storage */

    f.read(reinterpret_cast<char*>(&arr[0]), nbytes);   /* read file into vector */ 
    
    if (f.bad() || f.fail())                    /* validate read */
        return 1;

    for (auto& i : arr) /* output results (limit for larger files) */
        std::cout << std::hex << std::showbase << static_cast<uint32_t>(i) << " ";
    std::cout.put ('\n');
}

Look things over and let me know if you have further questions. There are several ways to approach this.

Upvotes: 2

Related Questions