最近,我构建了一个看似简单的text-to-char字符串阅读器,但它似乎在文件末尾返回奇怪的文本。
所以这是我正在尝试阅读的文件之一:
#version 330 core
in vec3 inputColour;
out vec4 outputColour;
void main()
{
outputColour = vec4(inputColour, 1.0f);
}
这是一个用GLSL编写的OpenGL着色器,fyi。但是,当我尝试“阅读”它时,它会返回:
请注意命令窗口末尾的四个2
个字符。当我尝试在运行时编译此着色器时,它会返回错误,其中包含一些不在原始文本中的字符。我创建了一个断点并进一步研究了它。我运行了该函数并打开了Text-Visualiser,它返回了这个:
同样,文本末尾还有另外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编辑器编写的文件进行了测试,两者都给了我相同的结果。
我确实找到了“解决方法”。也就是说,这是一个非常糟糕的hacky解决方法,这是非常糟糕的做法。基本上,您可以将[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]
。
答案 0 :(得分:1)
您没有确保缓冲区\0
已终止。将其设为inputFileSize+1
并在阅读后终止它。
像std::strlen(buffer)
这样的函数期待它。如果你试图在任何地方使用它而不提供长度,它将继续读取超过缓冲区的末尾。
此外,您需要delete[] buffer
,因为它已分配new[]
答案 1 :(得分: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(“C:\ example.txt”) .c_str(); const char*的等效std::string
>或将LoadFile(location)
保存到新的std::string
并使用.c_str()
。
注意,.c_str()
不能轻易“返回”,因为它是指向局部变量的指针。当函数结束时,该变量将被删除,.c_str()
变为空指针。我选择这样做的方法是在函数或API调用需要时使用.c_str()
。在C ++中,当您使用std::string
而不是char*
时,似乎可以省去很多麻烦,尤其是在使用基于文本的文件和 C ++标准库时。