
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で質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語での採番について
-
続・EOF判定されない
-
fopenで開いたファイルのサイズ...
-
VS2010 MFC CStdioFileについて
-
fgetsで2行目から文字化け
-
FTPでputすると空ファイルが出...
-
Access クエリ実行が急に非常に...
-
フルパスから最後のディレクト...
-
csvファイルを開かずに文字を検...
-
テキストファイルの最終行を削...
-
VB.NETで他のプロジェクトで作...
-
バッファとは何ですか
-
vba ActiveSheet.pasteを使った...
-
C言語初心者の質問失礼します。
-
UTL_FILEにて既存のExcelに追加...
-
c言語でファイルのタイムスタン...
-
シェルコマンドの 2>&1 とはど...
-
FTPでリモートのファイル一覧取得
-
ファイル出力の場所を指定
-
OLE又はDDEを使うVISUAL BESIC...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキストファイルの行数を取得...
-
ファイル内のデータを1行削除...
-
バイナリファイルをテキストフ...
-
fgetsで2行目から文字化け
-
ファイルサイズ指定し、ファイ...
-
c言語 2つのファイルを行ご...
-
0x00をファイル出力
-
C言語での採番について
-
VBSで指定行に挿入
-
テキストファイルの先頭への文...
-
fopen(ファイルパス)
-
C言語での改行コードの扱いにつ...
-
fopenで開いたファイルのサイズ...
-
winsock recvでの文字化け
-
EOF判定されない
-
fscanf関数のscanf集合を使う時...
-
巨大なテキストファイル(可変...
-
VS2010 MFC CStdioFileについて
-
(UWSC)このような場合、解決策...
-
改行までの一文字ずつのファイ...
おすすめ情報