How to convert byte array of uint8 to readable FString?

Hello unreal engineers,

I’m trying to write FString data to binary file in UE4, and I’ve been following Rama’s tutorial on writing data to files.

Thanks to his help I managed to write those two functions:

Save String Function


    FString SaveDirectory = FString("E:/UESaves");
	FString FileName = FString("UE4Save.bin");
	FString TextToSave = FString("YoungWolf?db235ccsa432ds");

	bool bAllowOverwriting = false;

	IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

	FString FullPath = SaveDirectory + "/" + FileName;

	IFileHandle* FileHandle = PlatformFile.OpenWrite(*FullPath);
	
	if (FileHandle)
	{
		FileHandle->Write((const uint8*)TCHAR_TO_ANSI(*TextToSave), TextToSave.Len());
	
		delete FileHandle;
	}

Load String Function


    FString SaveDirectory = FString("E:/UESaves");
	FString FileName = FString("UE4Save.bin");
	FString TextToSave = FString("YoungWolf?db235ccsa432ds");

	bool bAllowOverwriting = false;

	IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

	FString FullPath = SaveDirectory + "/" + FileName;

    IFileHandle* FileHandle = PlatformFile.OpenRead(*FullPath);

	if (FileHandle)
	{
		int64 size = GetFileSizeOf(FullPath);

		//Allocate uint8 buffer with size
		uint8* ByteArray = reinterpret_cast<uint8*>(FMemory::Malloc(size + 1));

		//Read Data to buffer
		FileHandle->Read(ByteArray, size);

		//Convert to decimal here..


		delete FileHandle;
	}

What I’ve tried is:
FString ActualString = FString::FromBlob(ByteArray, size);
FString ActualString = FString::FromHexBlob(ByteArray, size);

and been googleing around for hours, but sadly, no information on the topic. Can anyone help me?

UnrealString.h has BytesToString() and StringToBytes() functions.

1 Like

I just checked them out, but the converted string is not the same.
Original: YoungWolf?db235ccsa432ds
Recovered: ZpvohXpmg@ec346ddtb543et

Now that I compare them it feels like the original string had all the letters +1. Probably to the fact that when converting to binary, the original text that was UTF16 was converted to ANSI. Maybe that’s why it’s different?

So y +1 = z
o +1 = p

Now I can do either convert the recovered string with -1 to each individual letters, tho I’m not sure how. Would tchar - 1 work?

Or there is a way to get the string correctly?

Take a look here, maybe it helps:

https://answers.unrealengine.com/questions/460004/stringtobytesbytestostring-broken-for-some-charact.html

Hmm thanks for the link. Reading through it, and learned that the funcs are broken when passing UTF16 binary arrays. Haven’t been fixed since 12.5 version of the engine. Now what? Guess I’m in a dead end.

I was able to fix it. Here’s the function I wrote:


    FString Fixed;

	for (int i = 0; i < BrokenString.Len(); i++)
	{
		const TCHAR c = BrokenString* - 1;
		Fixed.AppendChar(c);
	}

	return Fixed;

I hope it might work out for someone out there who stuggles! Just note that it will only work if the entire string is broken.

3 Likes

Worked for me, I just made a wrapper function to make it easier on me:


FString BytesToStringFixed(const uint8 *In, int32 Count)
{
    FString Broken = BytesToString(In, Count);
    FString Fixed;

    for (int i = 0; i < Broken.Len(); i++)
    {
        const TCHAR c = Broken* - 1;
        Fixed.AppendChar(c);
    }

    return Fixed;
}

Had the same issue with 4.26.2, the Unreal engine issue report says they will not fix it. (Unreal Engine Issues and Bug Tracker (UE-33889))

I dont fully understand the implications of the null pointer terminator described in their comment:

// Put the byte into an int16 and add 1 to it, this keeps anything from being put into the string as a null terminator

But anyway I created my own function like this modifying theirs. So far seems to work ok.

inline FString UFileDownloader::MyBytesToString(const uint8* In, int32 Count)
{
FString Result;
Result.Empty(Count);

while (Count)
{
    int16 Value = *In;

    Result += TCHAR(Value);

    ++In;
    Count--;
}
return Result;

}

4 Likes

This does the trick

TArray<uint8> content;  
const std::string cstr(reinterpret_cast<const char*>(content.GetData()), content.Num());  
FString frameAsFString = cstr.c_str();  
UE_LOG(VRSLog, Warning, TEXT("%s"), *frameAsFString);

Doesn’t work for me.

For some reason it is returning empty.

TArray<uint8> ReceiveData;

FString result = FString(UTF8_TO_TCHAR(ReceiveData.GetData())); ← not safe enough

this works for non-ansi wide char , “像是中文”

FString result = FString(ReceiveData.Num(), UTF8_TO_TCHAR(ReceiveData.GetData())); ← this one better

2 Likes

this worked for me!