ゲームのセーブデータを読み込みたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
駆け出し
記事: 25
登録日時: 8年前

ゲームのセーブデータを読み込みたい

#1

投稿記事 by 駆け出し » 8年前

タイトルの通りですが、うまくいきません。セーブデータの日本語部分を読み込めない(見つけられない)のです。
セーブデータは*iniみたいな構造になっていて、
[tab=30]param = value
[tab=30]param = "string"
[tab=30]{
[tab=60]child_param = value
[tab=30]}
みたいになっています。今回うまくいかないのは
navy={
id={
id=802
type=61
}
name="大日本帝国第7艦隊"
movement_progress=8.400
override_move=yes
path={
2752
}
location=2729
logical_country="JAP"
base=9458
ship={
id={
id=3208
type=51
}
name="Hiyo"
のなかで"大日本"を見つけられない(Hiyoは見つけることができました)ことで、お手上げです。
コード

コード:

#include   <stdlib.h>
#include   <locale.h>
#include   <wchar.h>
#include   <errno.h>
#include <stdio.h>
#include <locale.h>
#include <tchar.h>
#include <vector>
#include <conio.h>
#include <Windows.h>
#include <io.h>
#include <fcntl.h>  
#include <sys/stat.h>
#include <mbstring.h>
#define INVALID_VALUE ((unsigned)(-1))

DWORD text_find(LPCSTR source,LPCSTR search,DWORD start)
{
	size_t sourcelength, searchlength;
	UCHAR *p;

	sourcelength = strlen(source) + 1;
	searchlength = strlen(search) + 1;

	if (start + searchlength > sourcelength)
		return INVALID_VALUE;

	if ((p = _mbsstr((unsigned char*)source + start,(unsigned char*)search)) == NULL) //strstrでも結果は同じ
		return INVALID_VALUE;

	return (DWORD)(strlen(source) - strlen((LPCSTR)p));
}

size_t GetFileSize(LPCSTR lpFileName)
{
	struct _stat stbuf;
	int fd;

	_sopen_s(&fd, lpFileName, _O_BINARY,
		_SH_DENYWR, _S_IREAD);
	if (fd == -1) {
		return INVALID_VALUE; //0xfffffff...
	}


	if (_fstat(fd, &stbuf) == -1) {
		/* エラー処理 */
		return INVALID_VALUE;
	}

	_close(fd);

	return stbuf.st_size;
}

//
int getfiletext(LPCSTR file, LPSTR *txt)
{
	FILE *fp;
	CHAR *cb;
	size_t s;

	s = GetFileSize(file);
	cb = (char*)malloc(s + 1);

	fopen_s(&fp, file, "rb");
	fread(cb, s, 1, fp);
	fclose(fp);


	*txt = cb;

	return TRUE;

}

//まだでばっぐしてないです
int GetParam(LPCSTR lpSaveData, DWORD start, CHAR **loaded)
{
	//その行のパラメを読み込む
	DWORD max = (DWORD)strlen(lpSaveData), i;
	CHAR *LoadedData;
	int paramlen = 0;

	for (i = start; lpSaveData[i] != '=' && max > i; i++) { Sleep(1); }

	i++;
	//もし"からはじまっているならi++
	if (lpSaveData[i] == '\"')
		i ++;

	for (DWORD j = i; lpSaveData[j] != '\n' && lpSaveData[j] != '\"'; j++)
		paramlen++;

	if ((LoadedData = (CHAR*)calloc(paramlen + 2, sizeof(CHAR))) == NULL)
		return FALSE;

	memcpy(LoadedData, lpSaveData + i, sizeof(CHAR)*paramlen);

	*loaded = LoadedData;

	return TRUE;
}

int main()
{
	CHAR *wtxt,*name;
	size_t pos;
	
	getfiletext("test.txt", &wtxt);


	if (text_find("あaあああaい", "い", 0) == INVALID_VALUE)
		return -1;

	//まず、あたりを付ける
	if ((pos = text_find(wtxt, "大日本", 0)) == INVALID_VALUE)
		return FALSE;

	
	return TRUE;

}
ーブデータを添付しておきます。引用は854872行目より数行です(解凍してください)
お手数ですが、BOMがついてしまっていたので(アカウントIDが保存されているのでそれを消すためにメモ帳で編集しました)、DLされた方はしなおしてください。
最後に編集したユーザー 駆け出し on 2017年5月21日(日) 20:35 [ 編集 2 回目 ]

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ゲームのセーブデータを読み込みたい

#2

投稿記事 by みけCAT » 8年前

UTF-8のファイルを読み込んでいるのに、SHIFT_JISの"大日本"を探しているので、見つからないのだと思います。
UTF-8で1バイトの文字のみからなる"Hiyo"は、表現が同じだったので見つかったのでしょう。

また、getfiletext関数内で読み込んだデータをナル終端していない(mallocで確保したバッファの初期値は不定)ので、
この関数で取得したデータ(へのポインタ)をそのままstrlenに放り込むのは危険です。
読み込んだデータの次のバイトにヌル文字'\0'を入れるべきです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

駆け出し
記事: 25
登録日時: 8年前

Re: ゲームのセーブデータを読み込みたい

#3

投稿記事 by 駆け出し » 8年前

UTF-8のファイルを読み込んでいる
BOMついてなかったので、四苦八苦してましたが、UTF-8なんですね。わかりませんでした。
また、getfiletext関数内で読み込んだデータをナル終端していない(mallocで確保したバッファの初期値は不定)ので、
この関数で取得したデータ(へのポインタ)をそのままstrlenに放り込むのは危険です。
読み込んだデータの次のバイトにヌル文字'\0'を入れるべきです。
ご指摘ありがとうございます。てっきりそのままcalloc使っていると思っていたのですが、malloc使ってました。コードを次のように修正しました。

コード:

int getfiletext(LPCSTR file, LPSTR *txt)
{
	FILE *fp;
	CHAR *cb;
	size_t s;
       /*エラーチェックなしになってますが、存在は今回確実にしているとします。*/
	s = GetFileSize(file);
	cb = (char*)calloc(s + 1, sizeof(CHAR));

	fopen_s(&fp, file, "rb");
	fread(cb, s, 1, fp);
	fclose(fp);


	*txt = cb;

	return TRUE;

}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ゲームのセーブデータを読み込みたい

#4

投稿記事 by みけCAT » 8年前

駆け出し さんが書きました:
UTF-8のファイルを読み込んでいる
BOMついてなかったので、四苦八苦してましたが、UTF-8なんですね。わかりませんでした。
添付されたファイルtest.txtにはBOMがついていましたが、どういう意味でしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

駆け出し
記事: 25
登録日時: 8年前

Re: ゲームのセーブデータを読み込みたい

#5

投稿記事 by 駆け出し » 8年前

駆け出し さんが書きました:
UTF-8のファイルを読み込んでいる
BOMついてなかったので、四苦八苦してましたが、UTF-8なんですね。わかりませんでした。
添付されたファイルtest.txtにはBOMがついていましたが、どういう意味でしょうか?
今しがた手元のコピー元ファイル確認してみたところBOMは付いていませんでした。メモ帳で編集したり、fopen_sでencodeを指定したりするとBOMってつきますか?これくらいしか思うところがないです。念のために、コピーしてzipしただけのものをおいておきます。
添付ファイル
JAP_1953_11_07_05.zip
BOMはついていない(FavBinEditで確認しました)物にまります。ご迷惑をおかけします。
(3.91 MiB) ダウンロード数: 174 回

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ゲームのセーブデータを読み込みたい

#6

投稿記事 by みけCAT » 8年前

駆け出し さんが書きました:念のために、コピーしてzipしただけのものをおいておきます。
このファイルにはBOMがついていないことを確認しました。
駆け出し さんが書きました:メモ帳で編集したり、fopen_sでencodeを指定したりするとBOMってつきますか?これくらいしか思うところがないです。
そう仮説を立てたら、まず実験してみてはいかがですか?
実験をすることで、一般につくかはわからなくても、つくことがあるかはわかるかもしれません。
実験はしましたか?したのであれば、結果はどうでしたか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

駆け出し
記事: 25
登録日時: 8年前

Re: ゲームのセーブデータを読み込みたい

#7

投稿記事 by 駆け出し » 8年前

そう仮説を立てたら、まず実験してみてはいかがですか?
実験をすることで、一般につくかはわからなくても、つくことがあるかはわかるかもしれません。
実験はしましたか?したのであれば、結果はどうでしたか?
メモ帳はつきますが、fopenはつきませんでした。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ゲームのセーブデータを読み込みたい

#8

投稿記事 by みけCAT » 8年前

データ変換ツール(BASE64, URLエンコード(URLデコード), HEX(16進ダンプ), MD5, SHA-1変換フォーム)
によると、"大日本"のUTF-8でのバイト列はe5a4a7e697a5e69cacなので、
"大日本"の代わりに"\xe5\xa4\xa7\xe6\x97\xa5\xe6\x9c\xac"を検索すると見つかるかもしれません。
(データを調べた所SHIFT_JISでは表現できない文字が含まれていたので、一旦入力をSHIFT_JISに変換して読み込ませるという方法はよくないかもしれないと思いました)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

駆け出し
記事: 25
登録日時: 8年前

Re: ゲームのセーブデータを読み込みたい

#9

投稿記事 by 駆け出し » 8年前

"大日本"の代わりに"\xe5\xa4\xa7\xe6\x97\xa5\xe6\x9c\xac"を検索すると見つかるかもしれません。
次のコードを実行したところ

コード:

int main(int argc, char **argv)
{
	char *txt;

	getfiletext("test.txt", &txt);
	return text_find(txt, "\xe5\xa4\xa7\xe6\x97\xa5\xe6\x9c\xac", 0);
}
'[7488] GetNavyInfo.exe ' はコード 15237921 (0xe88321) で終了しました。
-1ではないので発見できてるようです。ありがとうございます。
ただ、この「\xe5\xa4\xa7\xe6\x97\xa5\xe6\x9c\xac」はどうやって得るのでしょうか。
MultibyteToWideChar/WidecharToMulibyteでCP_ACPとCP_UTF8を指定すればいいですか?

駆け出し
記事: 25
登録日時: 8年前

Re: ゲームのセーブデータを読み込みたい

#10

投稿記事 by 駆け出し » 8年前

連投失礼します。事故解決しました。

コード:

//検索文字をSHIFT-jisからUTF-8に変換
BOOL ShiftJisToUTF8(LPCSTR lpShiftJis,LPSTR *Buffer)
{
	wchar_t *bufUnicode;
	char *utf8;

	// まずUniocdeに変換する
	// サイズを計算する
	int iLenUnicode = MultiByteToWideChar(CP_ACP, 0, lpShiftJis, strlen(lpShiftJis) + 1,
		NULL, 0);
	//バッファを確保
	if ((bufUnicode = (WCHAR*)calloc(iLenUnicode + 1, sizeof(WCHAR))) == NULL)
		return FALSE;
	
	MultiByteToWideChar(CP_ACP, 0, lpShiftJis, strlen(lpShiftJis) + 1, bufUnicode, iLenUnicode);
	// 次に、UniocdeからUTF8に変換する
	// サイズを計算する
	int iLenUtf8 = WideCharToMultiByte(CP_UTF8, 0, bufUnicode, iLenUnicode, NULL, 0, NULL, NULL);
	
	//バッファ確保
	if ((utf8 = (CHAR*)calloc(iLenUtf8 + 1, sizeof(CHAR))) == NULL)
	{
		free(bufUnicode);
		return FALSE;
	}



	WideCharToMultiByte(CP_UTF8, 0, bufUnicode, iLenUnicode, utf8, iLenUtf8, NULL, NULL);
	free(bufUnicode);

	*Buffer = utf8;

	return TRUE;
	
}


返信

“C言語何でも質問掲示板” へ戻る