Wide Text Reading

Started by
3 comments, last by KingofNoobs 11 years, 4 months ago
Hello,

I am outputting some Atlas and Sprite initialization data to a file. I am trying to keep everything in my game wide chars in Unicode for eventual localization purposes. I can reroute wcout to my file, but when I open it in notepad it is gibberish. I know notepad can read unicode because I save txt files in Unicode from time to time using Notepad. Can anyone tell me if I need a new text reader for wide characters, or how I can set up notepad to accept my wide char UNICODE file as unicode and read it appropriately?

Thanks again.

-Dave Ottley

I wonder as I wander...

http://www.davesgameoflife.com

Advertisement
Can you post your code, and a hex dump of the resulting text file? Is the file readable in, say, wordpad or word?

PS: ditch notepad - wordpad is superior in every single aspect (and if you want better, there's always notepad2, notepad++, etc...)

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

WARNING: This is long:
--------------------------------------
int main()
{
ifstream atlas("temp.atlas", ios::binary | ios::app | ios::ate);
uint32_t size = (uint32_t)atlas.tellg();
char * buffer = new char[size+1];
uint32_t imageDataStartsHere = 0;
atlas.seekg(0);
atlas.read(&buffer[0], size);
buffer[size] = 0;
atlas.close();

ofstream wcout("Atlas_Header_Logger.txt");
wcout << "The buffer is: " << size << L" bytes long." << endl;
wcout << L"The file is safely in memory." << endl;
wcout << endl << L"File Data:" << endl;
wcout << L"----------" << endl;
const uint32_t MAX_SPRITES = 100;
wstring atlasTitle;
uint32_t numOfSprites;
vector<wstring> spriteTitle; spriteTitle.reserve(MAX_SPRITES);
vector<uint32_t> frameWidth; frameWidth.reserve(MAX_SPRITES);
vector<uint32_t> frameHeight; frameHeight.reserve(MAX_SPRITES);
vector<uint32_t> originX; originX.reserve(MAX_SPRITES);
vector<uint32_t> originY; originY.reserve(MAX_SPRITES);
vector<uint32_t> numFrames; numFrames.reserve(MAX_SPRITES);
vector<uint32_t> sheetWidthInFrames; sheetWidthInFrames.reserve(MAX_SPRITES);
vector<uint32_t> sheetHeightInFrames; sheetHeightInFrames.reserve(MAX_SPRITES);
vector<uint32_t> numOfAnimations; numOfAnimations.reserve(MAX_SPRITES);
vector<vector<wstring>> animNames; animNames.reserve(MAX_SPRITES);
vector<vector<uint32_t>> animNumFrames; animNumFrames.reserve(MAX_SPRITES);
vector<vector<vector<uint32_t>>> animFrameList; animFrameList.reserve(MAX_SPRITES);

enum FileSection
{
ATLAS_TITLE,
NUM_OF_SPRITES,
SPRITE_NAME,
FRAME_WIDTH,
FRAME_HEIGHT,
ORIGIN_X,
ORIGIN_Y,
NUM_FRAMES,
SHEET_WIDTH_IN_FRAMES,
SHEET_HEIGHT_IN_FRAMES,
NUM_OF_ANIMATIONS,
ANIM_NAME,
ANIM_NUM_FRAMES,
ANIM_FRAMELIST,
ANIM_NEXT_FRAME,
END_OF_HEADER
};
FileSection currentFileSection = ATLAS_TITLE;
bool abort = false;
const uint32_t MAX_DIGITS = 4;
char numberBuffer[MAX_DIGITS + 1];
uint32_t digits = 0;
uint32_t letters = 0;
uint32_t spriteNum = 0;
uint32_t animationNum = 0;
uint32_t animationFrameNum = 0;
uint32_t spritesRemaining = 0;
uint32_t animationsRemaining = 0;
uint32_t animationFramesRemaining = 0;
bool newSprite = true;
bool newAnimation = true;
bool newAnimationFrame = true;
auto ExtractString = [&](wstring& dest, char source, FileSection& currentFileSection, FileSection nextFileSection, char* fieldTitle)
{
if(source != 0)
{
wchar_t wSource = (wchar_t) source;
dest += source;
++letters;
}
else
{
if(letters == 0)
{
wcout << "Error: Correct field not found in the original file." << endl;
abort = true;
}
else
{
letters = 0;
currentFileSection = nextFileSection;
string temp;
for(auto i = dest.begin(); i != dest.end(); ++i)
{
temp.insert(temp.end(), *i);
}
wcout << fieldTitle << " " << temp << endl;
}
}
};
auto ExtractInt = [&](uint32_t& dest, char source, FileSection& currentFileSection, FileSection nextFileSection, char* fieldTitle)
{
if(source >= '0' && source <= '9')
{
numberBuffer[digits] = source;
++digits;
}
else
{
if(digits == 0)
{
wcout << "Error: Field not found in the original file." << endl;
abort = true;
}
else // To next section
{
numberBuffer[digits] = 0;
digits = 0;
dest = atoi(numberBuffer);
currentFileSection = nextFileSection;
wcout << fieldTitle << " " << dest << endl;
}
}
};
for(unsigned i = 0; i < size; ++i)
{
switch(currentFileSection)
{
case ATLAS_TITLE:
{
ExtractString(atlasTitle, buffer, currentFileSection, NUM_OF_SPRITES, "Atlas Title: ");
break;
}
case NUM_OF_SPRITES:
{
ExtractInt(numOfSprites, buffer, currentFileSection, SPRITE_NAME, "Num Sprites: ");
break;
}
case SPRITE_NAME:
{
static bool first = true;

auto ResizeSprites = [&]()
{
spriteTitle.resize(spriteTitle.size() + 1);
frameWidth.resize(frameWidth.size() + 1);
frameHeight.resize(frameHeight.size() + 1);
originX.resize(originX.size() + 1);
originY.resize(originY.size() + 1);
numFrames.resize(numFrames.size() + 1);
sheetWidthInFrames.resize(sheetWidthInFrames.size() + 1);
sheetHeightInFrames.resize(sheetHeightInFrames.size() + 1);
numOfAnimations.resize(numOfAnimations.size() + 1);
animNames.resize(animNames.size() + 1);
animNumFrames.resize(animNumFrames.size() + 1);
animFrameList.resize(animFrameList.size() + 1);
};
if(first)
{
spritesRemaining = numOfSprites;
first = false;
}
if(newSprite)
{
wcout << endl;
ResizeSprites();
newSprite = false;
}

ExtractString(spriteTitle[spriteNum], buffer, currentFileSection, FRAME_WIDTH, "Sprite Name: ");
break;
}
case FRAME_WIDTH:
{
newSprite = true;
ExtractInt(frameWidth[spriteNum], buffer, currentFileSection, FRAME_HEIGHT, "Frame Width: ");
break;
}
case FRAME_HEIGHT:
{
ExtractInt(frameHeight[spriteNum], buffer, currentFileSection, ORIGIN_X, "Frame Height: ");
break;
}
case ORIGIN_X:
{
ExtractInt(originX[spriteNum], buffer, currentFileSection, ORIGIN_Y, "Origin X: ");
break;
}
case ORIGIN_Y:
{
ExtractInt(originY[spriteNum], buffer, currentFileSection, NUM_FRAMES, "Origin Y: ");
break;
}

case NUM_FRAMES:
{
ExtractInt(numFrames[spriteNum], buffer, currentFileSection, SHEET_WIDTH_IN_FRAMES, "Frames: ");
break;
}
case SHEET_WIDTH_IN_FRAMES:
{
ExtractInt(sheetWidthInFrames[spriteNum], buffer, currentFileSection, SHEET_HEIGHT_IN_FRAMES, "Width(Frames): ");
break;
}
case SHEET_HEIGHT_IN_FRAMES:
{
ExtractInt(sheetHeightInFrames[spriteNum], buffer, currentFileSection, NUM_OF_ANIMATIONS, "Height(Frames):");
break;
}
case NUM_OF_ANIMATIONS:
{
ExtractInt(numOfAnimations[spriteNum], buffer, currentFileSection, ANIM_NAME, "Animations: ");
break;
}
case ANIM_NAME:
{
auto ResizeAnimations = [&]()
{
animNames[spriteNum].resize(animNames[spriteNum].size() + 1);
animNumFrames[spriteNum].resize(animNumFrames[spriteNum].size() + 1);
animFrameList[spriteNum].resize(animFrameList[spriteNum].size() + 1);
};
if(newAnimation)
{
animationsRemaining = numOfAnimations[spriteNum];
ResizeAnimations();
newAnimation = false;
}
ExtractString(animNames[spriteNum][animationNum], buffer, currentFileSection, ANIM_NUM_FRAMES, "Anim Name: ");
break;
}
case ANIM_NUM_FRAMES:
{
ExtractInt(animNumFrames[spriteNum][animationNum], buffer, currentFileSection, ANIM_FRAMELIST, " Frames: ");
if(currentFileSection == ANIM_FRAMELIST)
{
animationFramesRemaining = animNumFrames[spriteNum][animationNum];
animFrameList[spriteNum][animationNum].resize(animationFramesRemaining);
}
break;
}
case ANIM_FRAMELIST:
{
if(animationFramesRemaining != 0)
{
ExtractInt(animNumFrames[spriteNum][animationNum], buffer, currentFileSection, ANIM_NEXT_FRAME, " #: ");
if(currentFileSection == ANIM_NEXT_FRAME)
{
--animationFramesRemaining;
if(animationFramesRemaining)
{
currentFileSection = ANIM_FRAMELIST;
break;
}
else // No frames remaining
{
--animationsRemaining;
if(animationsRemaining)
{
currentFileSection = ANIM_NAME;
}
else // No animations remaining
{
--spritesRemaining;
if(spritesRemaining)
{
currentFileSection = SPRITE_NAME;
}
else // No sprites remaining
{
currentFileSection = END_OF_HEADER;
}
}
}
}
}
switch(currentFileSection)
{
// Do this only once at the end of the animation
case ANIM_NAME:
{
++animationNum;
newAnimation = true;
break;
}

// Do this only once at the end of the last animation for this sprite
case SPRITE_NAME:
{
++spriteNum;
newSprite = true;
newAnimation = true;
break;
}
case ANIM_FRAMELIST:
{
break;
}
case END_OF_HEADER:
{
break;
}

default:
{
wcout << endl << "Heading to Unknown File Section. Aborting Program." << endl;
abort = true;
break;
}
} // switch
break;
} // ANIM_FRAMELIST
case END_OF_HEADER:
{
imageDataStartsHere = i + 1;
wcout << endl << "End of Header." << endl;
abort = true;
break;
}
default:
{
wcout << endl << "Unknwon File Section. Aborting Program." << endl;
abort = true;
break;
}
} // switch
if(abort) break;

} // for

wcout << endl;
delete[] buffer;
system("pause");
return 0;
}


-------
DUMP:

he buffer is: 88080020CF68
0020CF88
0020CFD0
0020CFEC
Atlas Title: Level1Atlas
Num Sprites: 4
Sprite Name: Title
Frame Width: 800
Frame Height: 300
Origin X: 0
Origin Y: 0
Frames: 1
Width(Frames): 1
Height(Frames): 1
Animations: 1
Anim Name: Default
Frames: 1
#: 0
Sprite Name: Background
Frame Width: 1
Frame Height: 1
Origin X: 800
Origin Y: 0
Frames: 1
Width(Frames): 1
Height(Frames): 1
Animations: 1
Anim Name: Default
Frames: 1
#: 0
Sprite Name: Play
Frame Width: 348
Frame Height: 119
Origin X: 0
Origin Y: 419
Frames: 2
Width(Frames): 2
Height(Frames): 1
Animations: 1
Anim Name: Default
Frames: 2
#: 0
#: 1
Sprite Name: Quit
Frame Width: 348
Frame Height: 119
Origin X: 0
Origin Y: 300
Frames: 2
Width(Frames): 2
Height(Frames): 1
Animations: 1
Anim Name: Default
Frames: 2
#: 0
#: 1
End of Header.

----------------------

Notice that when I use L"..." to output the file, I get garbage. When I don't use wide chars, it prints to file just fine. This is what I'm talking about.

I wonder as I wander...

http://www.davesgameoflife.com

An ofstream expects the strings output with << to be narrow character strings. If you want to use wide character strings use wofstream instead.
SiCrane,

Such a basic fix. Thank you very much.

I wonder as I wander...

http://www.davesgameoflife.com

This topic is closed to new replies.

Advertisement