![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
Winsockによりサーバ名、ポート番号、URLを指定するとそのソースファイルをテキスト出力するプログラミングを作成しています。
文字エンコーディングがShift_JISであるページは日本語も正しく表示させることができたのですが、それ以外の文字エンコーディング(EUC-JP、Unicode(UTF-8))のページでは日本語が文字化けしてしまいうまく出力できません。
デバックでrecv関数で文字を取得した際の変数szStrRcvを確認したところ、取得した時点で既に文字化けしているようです。
以下に問題部のソースを示します。
開発環境:WindowsXP Visualstudio.NET2003 VisualC++
WSADATA wsaData;
LPHOSTENT lpHost;
SOCKET s;
int nRtn;
SOCKADDR_IN sockadd;
_TCHAR szStrRcv[1024];
char szURL[1024]//URL
char szStr[256], szYN[4];
u_short sock_port;
unsigned int addr;
fp = fopen(filename, "a");
sock_port = (u_short)atoi(port);
s = socket(PF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) {
//perror("ソケットをオープンできません\n");
//WSACleanup();
//return -2;
}
lpHost = gethostbyname(host);
if (lpHost == NULL) {
addr = inet_addr(host);
lpHost = gethostbyaddr((char *)&addr, 4, AF_INET);
//wsprintf(szStr, "%sが見つかりません\n", host);
//perror(szStr);
//WSACleanup();
//return -3;
}
memset(&sockadd, 0, sizeof(sockadd));
sockadd.sin_family = AF_INET;
sockadd.sin_port = htons(sock_port);
sockadd.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);
if (connect(s, (PSOCKADDR)&sockadd, sizeof(sockadd)) != 0) {
//perror("サーバーソケットに接続失敗\n");
closesocket(s);
}
wsprintf(szStr, "GET %s\n", szURL);//szURLには正常にURLが入っている
nRtn = send(s, szStr, (int)strlen(szStr), 0);
while(1) {
memset(szStrRcv, '\0', sizeof(szStrRcv));
///////////////////////////問題の部分/////////////////////////////
nRtn = recv(s, szStrRcv, (int)sizeof(szStrRcv) - 1, 0);
_ftprintf(fp, _T("%s\n"), szStrRcv);//HTMLソースを.txtに書き込む
//////////この時点でszStrRcvには日本語が文字化けした内容が格納されている///////////////
if (nRtn == 0)
break;
if (nRtn == SOCKET_ERROR) {
perror("recvエラーです\n");
break;
}
}
closesocket(s);
WSACleanup();
fclose(fp);
何か対策がありましたらご教授をお願いいたします。
No.2ベストアンサー
- 回答日時:
>_ftprintf(fp, _T("%s\n"), szStrRcv); //HTMLソースを.txtに書き込む
>//////////この時点でszStrRcvには日本語が文字化けした内容が格納されている///////////////
文字化けも何も、EUCやUTF-8でエンコードされたページは「EUCやUTF-8のまま」送られて来るので、そのまま表示しても文字化けしてて当たり前。
ちゃんと表示したいなら、何のコードで送られて来たか見て、自分で「EUC⇒Shift_JIS」や「UTF-8⇒Shift_JIS」に変換してあげないとならない。
あと
_ftprintf(fp, _T("%s\n"), szStrRcv);
はやってはダメ。
1回の受信は「多バイト文字の、文字の途中」で途切れる可能性があるので、勝手に改行を足してはいけない。
例えば、漢字の「亜」は、UTF-8で「E4 BA 9C」の3バイトだが、1回のrecvで「E4 BA」までしか来ず、次のrecvで続きの「9C … …」が来る事もある。
それを
_ftprintf(fp, _T("%s\n"), szStrRcv);
などと「バカな事」をしてしまうと、受信テキストは「E4 BA 改行 9C」となって、漢字の「亜」の途中に改行コードを入れてしまう。
これでは「文字化けして当たり前」だろう。
てゆか、Shift_JISでも「亜」は「88 9F」の2バイトなんだから、勝手に改行を足してたら「88 改行 9F」って感じで、文字化けしてる筈。今まで文字化けしてたのに気が付かなかっただけで。
No.3
- 回答日時:
もう1つ。
>HTMLソースを.txtに書き込む
もし、UTF-8のコードのまま.txtに保存し、それをメモ帳で開いて正しく表示したいのなら、ファイルの先頭に「Byte Order Mark(BOM)」が無いといけない。
マイクロソフトの仕様では、UTF-8で保存されたテキストファイルの先頭には「EF BB BF」がある事になっている。
なので、ファイルの先頭にこの3バイトが無いと、メモ帳で開いた瞬間にUTF-8とは認識されず「文字がグチャグチャ」に文字化ける。
なお、メモ帳はEUCに対応してないので、EUCは必ず文字化ける。
わかりました。
貴方様の意見を参考にもう少し自分で調べてみます。
現段階でなんとか文字列をANSIに変換してtxtに保存できるようになりました。
ご教授ありがとうございました。
No.1
- 回答日時:
1.文字化けはどこで確認しましたか?
単純にEUCやUTF-8を認識できないプログラムで見ているだけではないですか?
VisualStudioのウォッチ画面などではShift-JIS以外の文字列を表示することはできないはずです。
2.全てのデータを受信していますか?
recvでは要求ファイルの全サイズを一度に読み込むわけではありません。
通信環境により、例えば10kのファイルだったとしても1バイトしか読み込まない可能性もありえます。
以下のようにやるのが定番だと思います。
char buf[10*1024] = {0}; // 十分なサイズを用意しておく事
int offset = 0;
int r = 1
while(r > 0)
{
// ネットワークからデータを読み込む。
// 返り値が正の数だったら、まだデータが残っている可能性がある
// 0だったら全てのデータを読み込んでサーバから切断された
// 負数だったらエラーが発生した
r = recv(s, &buf[offset], sizeof(buf)-offset-1, 0);
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- オープンソース Flaskでサーバー立ち上げに関して 1 2023/08/12 21:02
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- JavaScript HTMLでJavaScriptを使ってパスワードの強化判定のプログラムを作成しています。 一通り作っ 2 2022/10/19 01:41
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バイナリファイルをテキストフ...
-
ファイル内のデータを1行削除...
-
ファイルサイズ指定し、ファイ...
-
テキストファイルの各行の文字...
-
VBSで指定行に挿入
-
c言語 2つのファイルを行ご...
-
ハフマン符号のプログラム
-
fclose(fp);
-
VC++6でfgets関数の変わりにな...
-
fgetsで2行目から文字化け
-
freadとfwrite
-
テキストファイルの行数を取得...
-
C言語のfeof関数について質問
-
テキストファイルの文字列の削除
-
Active Basic EditBoxや文字列...
-
C言語初心者の質問失礼します。
-
バッファとは何ですか
-
フルパスから最後のディレクト...
-
どんなプログラムを書いても指...
-
「UNCパスはサポートされません...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ファイル内のデータを1行削除...
-
テキストファイルの行数を取得...
-
バイナリファイルをテキストフ...
-
fgetsで2行目から文字化け
-
VBSで指定行に挿入
-
ファイルサイズ指定し、ファイ...
-
c言語 2つのファイルを行ご...
-
freadとfwrite
-
winsock recvでの文字化け
-
【VB.Net】バイト型配列に読み...
-
C言語での改行コードの扱いにつ...
-
fopen(書き込みモード)でファイ...
-
fortranで文字列を読み込む際の...
-
EOF判定されない
-
改行までの一文字ずつのファイ...
-
InternetReadFileで大きいファ...
-
freadでファイルを読み込んだ際...
-
C言語での採番について
-
複数テキストファイルを読み込...
-
C言語 バイナリファイルの読み...
おすすめ情報