从文件中读取单个字符 returns 个特殊字符?

Reading a single character from a file returns special characters?

我正在尝试使用 fstreams 从文件中的指定位置读取单个字符并将它们附加到字符串中。出于某种原因,读入这些字符 returns 个特殊字符。我已经尝试了很多东西,但我在调试时发现的更奇怪的事情是更改 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;
}

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

For ASCII characters with a numeric value greater than 127, the actual character rendered on screen depends on the code page of the system you are currently using.

可能发生的情况是您没有像您认为的那样得到一个 "character"。

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

例如,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