2016-07-15 106 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。 –