Short post today to get this one out of the knowledge banks and onto the internet.
There are a lot of reasons you may need to import text-based tables into UE5. You might be building your own editor modules. You might be using data assets instead of data tables. You might be building a VO pipeline and need to import and export states from the recording sheet. Fortunately, there’s a format for that!
If you search for this in the official documentation, you’ll likely find this article in the official Unreal Learning Community: CSV to Data Table manipulation
It details a method for reading from CSV files in C++. The only problem is: it doesn’t really “work”, so to speak. It might, but it probably won’t.
It contains the following line of code:
aString.ParseIntoArray(stringArray, TEXT(","), false);
It will probably not work for you because it is a simple string split. If you have any commas in your text fields, they will be taken to be new fields. This is the correct and expected behavior for that function, but it was “fixed” to help with CSV files in UE4.5, and at an unknown time has been adjusted back to a basic string split. So the function itself is fine, but it’s not the right one to use because it can fail depending on your data.
Secondarily, when I tried the method it uses to load the CSV file, it failed every time:
FFileHelper::LoadANSITextFileToStrings(*CsvFile, NULL, Lines);
If you want it to actually work:
Use
FFileHelper::LoadFileToString
to load the file into a string.Use the
CsvParser
module to parse the string you just loaded.
This is confirmed working on 5.3+, although be aware “Load File To String” will fail if the file is open in another program; it does attempt an exclusive read so please close/save your CSV before importing via this method.
#include "Serialization/Csv/CsvParser.h"
FString CsvFile = *(FilePath + "\\filename.csv"); // filepath
FString CsvString; // string to load csv into
if (FPaths::FileExists(CsvFile))
{
FFileHelper::LoadFileToString(CsvString, *CsvFile);
FCsvParser CsvParser = FCsvParser(CsvString);
TMap<FString, TArray<FString>> CsvData;
for (auto& Row : CsvParser.GetRows())
{
UE_LOG(LogCategory, Display, TEXT("1: %s\n2: %s\n3: %s\n4: %s\n5: %s\n"), Row[0], Row[1], Row[2], Row[3], Row[4]);
}
}
And while you’re here, a quick sample for writing CSV files.
FString CSVOutputFileContents = TEXT("Line_ID,Character,Dialogue Text,Status\n"); // CSV header row
TCHAR Format[35] = TEXT("\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n"); // format for printf
for (auto& Row : SomeIterableThing)
{
CSVOutputFileContents += FString::Printf(Format, *Line_ID, *CharacterName, *DialogueText, *Status); // iterate over your things and write one row each here
}
FFileHelper::SaveStringToFile(CSVOutputFileContents, *(FilePath + "\\recording-export.csv")); // finally, save the file
This took up way too much of my Tuesday. I write it down so as to potentially save yours.
Until next time.
// for those we have lost
// for those we can yet save