从文件中读取单个字符会返回特殊字符吗?

时间:2015-08-23 15:44:34

标签: c++ fstream

使用fstreams我试图从文件中的指定位置读取单个字符并将它们附加到字符串上。出于某种原因,读取这些字符会返回特殊字符。我尝试了很多东西,但是我在调​​试时发现的更奇怪的事情是更改char temp;的初始值将导致整个字符串更改为该值。

int Class::numbers(int number, string& buffer) {
    char temp;

    if (number < 0 || buffer.length() > size) {
        exit(0);
    }

    string fname = name + ".txt";
    int start = number * size;

    ifstream readin(fname.c_str());
    readin.open(fname.c_str(), ios::in)
    readin.seekg(start);

    for (int i = 0; i < size; ++i) {
        readin.get(temp);
        buffer += temp;
    }

    cout << buffer << endl;
    readin.close();
    return 0;
}

以下是输出的特殊字符的示例屏幕截图:http://i.imgur.com/6HCI7TT.png

问题可能是我开始使用seekg的问题吗?它似乎从适当的位置开始。我考虑过的另一件事是,我可能会在流中读到一些无效的地方,它只是从内存中给我一些垃圾字符。

有什么想法吗?

工作解决方案

int Class::numbers(int number, string& buffer) {
    char temp;

    if (number < 0 || buffer.length() > size) {
        exit(0);
    }

    string fname = name + ".txt";
    int start = number * size;

    ifstream readin(fname.c_str());
    readin.open(fname.c_str(), ios::in)
    readin.seekg(start);

    for (int i = 0; i < size; ++i) {
        readin.get(temp);
        buffer += temp;
    }

    cout << buffer << endl;
    readin.close();
    return 0;
}

这是工作解决方案。在我的程序中,我已经打开了这个文件名,因此打开它两次可能会导致我想到的问题。我会在自己的时间里对此进行一些进一步的测试。

1 个答案:

答案 0 :(得分:1)

For ASCII characters with a numeric value大于127,屏幕上呈现的实际角色取决于code page of the system you are currently using

可能发生的事情是你没有像你想象的那样得到一个“角色”。

首先,要对其进行调试,请使用现有代码打开并打印整个文本文件。你的程序能够做到这一点吗?如果没有,您打开的“文本”文件可能不是使用ASCII,而是使用UTF或其他形式的编码。这意味着当你读到一个“字符”(最有可能是8位)时,你只是读取了16位“宽字符”的一半,结果对你来说毫无意义。

例如,gedit应用程序将自动呈现屏幕上的“Hello World”,正如我所期望的那样,无论字符编码如何。但是,在十六进制编辑器中,UTF8编码的文件如下所示:

UTF8原始文字:

0000000: 4865 6c6c 6f20 776f 726c 642e 0a         Hello world..

虽然UTF16看起来像:

0000000: fffe 4800 6500 6c00 6c00 6f00 2000 7700  ..H.e.l.l.o. .w.
0000010: 6f00 7200 6c00 6400 2e00 0a00            o.r.l.d.....

这是您的计划所看到的。 C / C ++默认使用ASCII编码。如果您想处理其他编码,则可以通过手动或使用第三方库来支持您的程序。

Also, you aren't testing to see if you've exceeded the length of the file。你可以抓住随机的垃圾。

使用只包含字符串“Hello World”的简单文本文件,您的程序可以执行此操作:

代码清单

// read a file into memory
#include <iostream>     // std::cout
#include <fstream>      // std::ifstream
#include <string.h>

int main () {
    std::ifstream is ("test.txt", std::ifstream::binary);
    if (is) {
        // get length of file:
        is.seekg (0, is.end);
        int length = is.tellg();
        is.seekg (0, is.beg);

        // allocate memory:
        char * buffer = new char [length];

        // read data as a block:
        is.read (buffer,length);
        // print content:
        std::cout.write (buffer,length);
        std::cout << std::endl;

        // repeat at arbitrary locations:
        for (int i = 0; i < length; i++ )
        {
            memset(buffer, 0x00, length);
            is.seekg (i, is.beg);
            is.read(buffer, length-i);
            // print content:
            std::cout.write (buffer,length);
            std::cout << std::endl;
        }

        is.close();
        delete[] buffer;
    }

    return 0;
}

示例输出

Hello World

Hello World

ello World

llo World

lo World

o World

 World

World

orld

rld

ld

d