2016-07-15 69 views
0

最近,我构建了一个看似简单的文本到字符串读取器,但它似乎返回文件结尾的奇怪文本。文件读取返回损坏的文件结尾

因此,这里是我试图读取文件之一:

#version 330 core 
in vec3 inputColour; 

out vec4 outputColour; 

void main() 
{ 
    outputColour = vec4(inputColour, 1.0f); 
} 

这是写在GLSL的OpenGL着色,仅供参考。然而,当我尝试“读”它,它返回:

Console Output

注意在命令窗口的最后四个2字符。当我在运行时尝试编译该着色器时,它会返回一些字符不在原始文本中的错误。我创建了一个断点并进一步研究它。我跑的功能,开辟了文本Visualiser的,它返回此:

Text Visualiser Image

同样,在有文字,ýýýý结束的另外4个字符。


这里的文本阅读器的代码:

std::ifstream inputFile("foo.txt", std::ios::in|std::ios::binary|std::ios::ate); 
int inputFileSize; 
char* buffer = ""; 

if (inputFile.is_open()) 
{ 
    inputFile.seekg(0, std::ios::end); //Set the cursor to the end. 
    inputFileSize = (int)inputFile.tellg(); //Set inputFileSize to the position of the cursor. 
    buffer = new char[inputFileSize]; //Create the buffer and set its size to the inputFileSize. 
    inputFile.seekg(0, std::ios::beg); //Move the cursor to the beginning. 
    inputFile.read(buffer, inputFileSize); //Read the file from the beginning. 
    inputFile.close(); //Close the file 
} 

我的猜测是,它可能有一些做与正在阅读不当行尾。不过,我用Notepad ++和内部Visual Studio编辑器编写的文件进行了测试,两者都给了我相同的结果。

我确实设法找到了“解决方法”。也就是说,这是一个非常糟糕的解决方法,这是非常糟糕的做法。基本上,你可以把[FILEEND]和你读的任何文本文件的末尾。虽然代码允许同时使用[FILEEND]或完全不使用,但代码需要使用[FILEEND]才能正确读取文件。

char* fileend = std::strstr(buffer, "[FILEEND]"); //Find [FILEEND]. 
int actualfilelen = fileend != NULL ? std::strlen(buffer) - std::strlen(fileend) : std::strlen(buffer); //Get the length of the main content of txt file. 
//If there is no [FILEEND] then return the size of the buffer without any adjustments. 
char* output = new char[actualfilelen + 1]; //Create new string with the length of the main content of txt file. 
std::strncpy(output, buffer, actualfilelen); //Copy main content of buffer to output. 
output[actualfilelen] = '\0'; //Add escape sequence to end of file. 
delete(buffer); //Deletes the original buffer to free up memory; 

然后我们只是返回output变量。 我不想在我的文件末尾使用[FILEEND]关键字(?),因为它们瞬间便携性降低。一个或两个文件与[FILEEND]可能没问题,但如果我有数百个文件,我想在另一个项目中使用,它们都将具有[FILEEND]

回答

1

分配我想出了一个解决方案,但它涉及到使用std::string,然后用string.c_str()将其转换。

std::string LoadFile(const char* FileLocation) 
{ 
    std::ifstream fileStream; 
    std::string fileOutput, currentLine; 
    fileStream.open(FileLocation); 
    if (fileStream.is_open()) 
    { 
     while (!fileStream.eof()) 
     { 
      std::getline(fileStream, currentLine); 
      fileOutput.append(currentLine + "\n"); 
      std::cout << "> " << currentLine << "\n"; 
     } 
    } 

    fileStream.close(); 

    return fileOutput; 
} 

然后你就可以找到这样做的LoadFile的std::stringconst char*基于当量( “C:\ example.txt文件”)。c_str();或将LoadFile(location)保存为新的std::string并在其上使用.c_str()

请注意,.c_str()不能简单地“返回”,因为它是一个指向局部变量的指针。当函数结束时,该变量将被删除并且.c_str()变为空指针。我选择的方式是在功能或API调用需要时使用.c_str()。在C++中,当使用std::string而不是char*时,尤其是在使用基于文本的文件和C++标准库时,似乎可以节省很多麻烦。

1

你没有确定缓冲区是\0终止。使其成为inputFileSize+1并在阅读后终止它。

std::strlen(buffer)这样的函数期望它。如果您尝试在没有提供长度的情况下在任何位置使用它,它会继续读取缓冲区的末尾。

此外,您还需要delete[] buffer,因为它是用new[]

+0

我已经编辑了我的代码,看起来像这样:http://pastebin.com/rhdEHP7X虽然运行时编译器现在读取这完全正常,但文本现在最后有'íííííííí'。我试图将文本编码从Unicode更改为ANSI,并且什么也没做。我也尝试使用printf函数,但它显示了完全相同的结果。我不明白这是怎么发生的,因为缓冲区被设置为一个长度并输出更多?例如,我的一个文件有130个字符。在检查员中,我检查了'inputFileSize'是130,它是。现在缓冲区应该是131,但事实并非如此。 –

+0

我也删除了我的着色器上的'[FILEEND]'关键字,并删除了[[FILEEND]'缩短代码。我现在不能删除缓冲区,因为它现在是函数的输出,除非它应该被“复制”到另一个数组并被删除。 –

+0

使用输入文件发布一个最小和完整的程序。重视最低限度。我应该可以在没有编辑和重现的情况下使用gcc。 –