【问题标题】:using fstream to read every character including spaces and newline使用 fstream 读取每个字符,包括空格和换行符
【发布时间】:2010-09-12 03:07:38
【问题描述】:

我想用fstream 来读取一个txt文件。

我正在使用inFile >> characterToConvert,但问题是它省略了任何空格和换行符。

我正在编写一个加密程序,所以我需要包含空格和换行符。

完成此任务的正确方法是什么?

【问题讨论】:

    标签: c++ newline spaces fstream


    【解决方案1】:

    我也发现ifstream对象的get()方法也可以读取文件的所有字符,不需要unset std::ios_base::skipws。引自C++ Primer

    几个未格式化的操作一次处理一个字节的流。这些操作在表 17.19 中进行了描述,读起来宁愿忽略空格。

    这些操作列表如下: is.get()os.put()is.putback()is.unget()is.peek()

    以下是最低工作代码

    #include <iostream>
    #include <fstream>
    #include <string>
    
    int main(){
        std::ifstream in_file("input.txt");
    
        char s;
    
        if (in_file.is_open()){
            int count = 0;
            while (in_file.get(s)){
    
                std::cout << count << ": "<< (int)s <<'\n';
                count++;
            }
    
        }
        else{
            std::cout << "Unable to open input.txt.\n";
        }
        in_file.close();
    
        return 0;
     }
    

    输入文件(cat input.txt)的内容是

    ab cd
    ef gh
    

    程序的输出是:

    0: 97
    1: 98
    2: 32
    3: 99
    4: 100
    5: 10
    6: 101
    7: 102
    8: 32
    9: 103
    10: 104
    11: 32
    12: 10
    

    10 和 32 是换行符和空格字符的十进制表示。很明显,所有字符都被读取了。

    【讨论】:

      【解决方案2】:

      可能最好的方法是将整个文件的内容读入一个字符串,使用 ifstream 的rdbuf() 方法可以很容易地做到这一点:

      std::ifstream in("myfile");
      
      std::stringstream buffer;
      buffer << in.rdbuf();
      
      std::string contents(buffer.str());
      

      既然您已经从文件中获取了所有内容,那么您就可以使用常规的字符串操作了。

      虽然Tomek 询问有关读取文本文件的问题,但读取二进制数据的方法相同,尽管在创建输入文件流时需要提供 std::ios::binary 标志。

      【讨论】:

      • 我怎样才能更多地支持这个。这可以为我节省数小时的编码时间...您会被本网站上存在的 糟糕 建议(即使是经验丰富的堆栈用户)所震撼。
      【解决方案3】:

      另一种更好的方法是使用istreambuf_iterator,示例代码如下:

      ifstream inputFile("test.data");
      
      string fileData(istreambuf_iterator<char>(inputFile), istreambuf_iterator<char>());
      

      【讨论】:

        【解决方案4】:
        ifstream ifile(path);
        std::string contents((std::istreambuf_iterator<char>(ifile)), std::istreambuf_iterator<char>());
        ifile.close();
        

        【讨论】:

          【解决方案5】:
          std::ifstream ifs( "filename.txt" );
          
          std::string str( ( std::istreambuf_iterator<char>( ifs ) ), 
                           std::istreambuf_iterator<char>()
                         );
          

          【讨论】:

            【解决方案6】:

            对于加密,您最好以二进制模式打开文件。使用类似这样的东西将文件的字节放入向量中:

            std::ifstream ifs("foobar.txt", std::ios::binary);
            
            ifs.seekg(0, std::ios::end);
            std::ifstream::pos_type filesize = ifs.tellg();
            ifs.seekg(0, std::ios::beg);
            
            std::vector<char> bytes(filesize);
            
            ifs.read(&bytes[0], filesize);
            

            编辑:根据 cmets 修复了一个微妙的错误。

            【讨论】:

            • 对不起,这有一个微妙的错误。调用仅采用偏移量的“seekg”重载,您最终只读取两个字节(“std::ios:end”的值)。你应该调用 seekg(0, std::ios::end) 和 seekg(0, std::ios::beg)。
            【解决方案7】:

            简单

            #include <fstream>
            #include <iomanip>
            
            
            ifstream ifs ("file");
            ifs >> noskipws
            

            就是这样。

            【讨论】:

            • 你的意思是“ifs >> noskipws >> some_string”吗?
            【解决方案8】:

            正如 Charles Bailey 正确指出的那样,您不需要 fstream 的服务来读取字节。所以忘记这个 iostream 愚蠢,使用 fopen/fread 并完成它。 C stdio 是 C++ 的一部分,你知道 ;)

            【讨论】:

            • 但是通过使用流,流不必只是一个文件。它可以是一个字符串、一个套接字或任何你喜欢的东西。 streambuf_iterator
            • 我同意,但 OP 明确表示目标是“读取 txt 文件”。
            【解决方案9】:

            istream 层的许多好处是为简单类型 ro 和来自流的类型提供基本格式和解析。出于您描述的目的,这些都不重要,您只是对文件作为字节流感兴趣。

            出于这些目的,您最好只使用 filebuf 提供的 basic_streambuf 接口。 “跳过空白”行为是您不需要的 istream 接口功能的一部分。

            filebuf 是 ifstream 的基础,但直接使用它是完全有效的。

            std::filebuf myfile;
            myfile.open( "myfile.dat", std::ios_base::in | std::ios_base::binary );
            
            // gets next char, then moves 'get' pointer to next char in the file
            int ch = myfile.sbumpc();
            
            // get (up to) the next n chars from the stream
            std::streamsize getcount = myfile.sgetn( char_array, n );
            

            还可以查看函数 snextc(将“get”指针向前移动,然后返回当前字符)、sgetc(获取当前字符但不移动“get”指针)和 sungetc(备份如果可能,将指针“获取”一个位置)。

            当您不需要 istream 类提供的任何插入和提取运算符而只需要一个基本的字节接口时,通常 streambuf 接口(filebuf、stringbuf)比 istream 接口(ifstream、istringstream)更合适.

            【讨论】:

              【解决方案10】:

              您可以调用int fstream::get(),它将从流中读取单个字符。您还可以使用istream&amp; fstream::read(char*, streamsize),它与get() 执行相同的操作,只是在多个字符上。给定的链接包括使用每种方法的示例。

              我还建议以二进制模式进行读写。这允许正确地从文件读取和写入 ASCII 控制字符。否则,加密/解密操作对可能会产生不相同的文件。为此,您使用ios::binary 标志打开文件流。对于二进制文件,您想使用read() 方法。

              【讨论】:

                【解决方案11】:

                对于加密,您可能应该使用read()。加密算法通常处理固定大小的块。哦,要以二进制模式打开(没有从 \n\r 到 \n 的转换),请将 ios_base::binary 作为第二个参数传递给构造函数或 open() 调用。

                【讨论】:

                  【解决方案12】:

                  我没有对此进行测试,但我认为您需要清除“跳过空白”标志:

                  inFile.unsetf(ios_base::skipws);
                  

                  我对 C++ 流使用以下参考: IOstream Library

                  【讨论】:

                  • 是的,如果你想读取二进制数据,肯定需要添加这个,因为它默认是打开的。
                  • 除了 ios::binary 标志之外,我也需要这个
                  【解决方案13】:

                  以下 c++ 代码将读取整个文件...

                  #include <iostream> #include <fstream> #include <string> using namespace std; int main () { string line; ifstream myfile ("foo.txt"); if (myfile.is_open()){ while (!myfile.eof()){ getline (myfile,line); cout << line << endl; } myfile.close(); } return 0; }

                  发布您的代码,我可以为您的问题提供更具体的帮助...

                  【讨论】:

                  猜你喜欢
                  • 2012-11-11
                  • 2018-05-24
                  • 1970-01-01
                  • 2014-06-03
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多