fgetsでファイルを一行ずつ読み込みたいのですが、二行目以降が文字化けしてしまいます。
*******
ソース
*******
#include <windows.h>
#include <stdio.h>
FILE *fp;
if ((fp = fopen("textlist.txt", "r")) == NULL){
MessageBox(NULL, TEXT("ファイルを開けません"), NULL, NULL);
exit (1);
}
while (1) {
TCHAR buf[128] = {0};
if (fgets(buf, sizeof(buf), fp) == NULL) break;
MessageBox(NULL,buf,NULL,NULL);
}
fclose(fp);
*****
textlist.txt
*****
あいうえお
かきくけこ
さしすせそ
メッセージボックスの一回目は正しく"あいうえお"と表示されますが、二回目・三回目は文字化けしています。
最終的に一行ずつ分けて配列に入れたいので、fgetsで出来たらと思っています。
よろしくお願いします。
No.6ベストアンサー
- 回答日時:
わかりました。
ちょっと事情があって VC7.1(2003)で試したのですが
2005でも同じだと思います。
MSDNによると
fgets、fgetws (CRT)
http://msdn2.microsoft.com/ja-jp/library/c37dh6k …
fgetws は、ワイド文字引数 str の読み出しを行い、stream がテキスト モードで開かれた場合はマルチバイト文字列として、バイナリ モードで開かれた場合はワイド文字列として読み出します。
とありますので、テキストをUnicodeで書いていたとしても、
if ((fp = fopen("textlist.txt", "r")) == NULL){
のようにテキストモードでオープンしてしまうと、
_fgetts(実体は fgetws)で読み込んだときに自動的に
ShiftJISに変換されてしまいます。
#実際はもうちょっと手が入るようですが
fopen(, "r")/fgets の組み合わせで2行目以降が
化けるのは前回の説明でいいとして、
結局のところ、
"rb" で fopen(もしくは _tfopen)を呼び出し、
fgetws(か _fgetts)で読み込んで
MessageBoxWで表示
のようにしないといけないようです。
#define _UNICODE
#define UNICODE
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
int
main()
{
FILE *fp;
if ((fp = _tfopen(TEXT("textlist.txt"), TEXT("rb"))) == NULL){
MessageBox(NULL, TEXT("ファイルを開けません"), NULL, 0);
exit (1);
}
while (1) {
TCHAR buf[128] = {0};
if (_fgetts(buf, sizeof(buf), fp) == NULL)
break;
MessageBox(NULL, buf, NULL, 0);
}
fclose(fp);
return 0;
}
こんな感じのでとりあえず動いているようです。
#ただし あいうえおの前にゴミが出る
テキストファイルの文字コードはメモ帳の Unicode でいいです。
できました!ありがとうございます。
バージョン違いからか、こちらでは前にゴミは出ませんでした^^
何度も回答いただいて、ありがとうございました。
No.5
- 回答日時:
すみません。
見落としと勘違いがありました。
> if (fgets(buf, sizeof(buf), fp) == NULL) break;
のように fgets を使っていますが、これではUnicodeが使われている
テキストファイルを正しく読むことができません。
というのも、行末の改行は(WindowsではLittle EndianのUnicodeなので)
0x0d 0x00 0x0a 0x00 のようになりますが、fgetsはこれがUnicodeであるとは
みなしていないので、0x0a まで読み進めたところで行末を見つけたと
判定してしまいます。
当然次の行は 0x00から始めますので、見事に位置がずれてしまうというわけです。
ファイルの先頭行はこういうずれは決して起きないので、正しく表示されていた。
というわけです。
ということで fgets を _fgetts に置き換えてやればよいのではないでしょうか?
fgets、fgetws (CRT)
http://msdn2.microsoft.com/ja-jp/library/c37dh6k …
この回答への補足
_fgettsにしましたが、最初から文字化けしてしまいました。
テキストファイルをBigEndianにしても、文字化けしました・・
No.4
- 回答日時:
テキストをShiftJISで書いたものにして、
マルチバイト文字環境でコンパイルすると文字化けは起きませんでした。
で、
> テキストファイルはXPのメモ帳でUnicodeで保存。
ということなので、メモ帳で同じようなテキストを作って確認したところ、
00000000: FF FE 42 30 44 30 46 30 48 30 4A 30 0D 00 0A 00 .~B0D0F0H0J0....
00000010: 4B 30 4D 30 4F 30 51 30 53 30 0D 00 0A 00 55 30 K0M0O0Q0S0....U0
00000020: 57 30 59 30 5B 30 5D 30 0D 00 0A 00 W0Y0[0]0....
のようになっています。
多分、MessgeBoxWに渡すテキストには BOMが必要なのに、
ファイルからとってきたテキストでは
ファイルの先頭にしかBOMがないので正しい
Unicodeによる適すとしてみてくれなくて
結果として化けたんじゃないですかね。
メモ帳で、Unicode(Big Endian) でセーブしたテキストだと
どうなりますか?
No.3
- 回答日時:
★コンパイラは何ですか?
・もしも VC++2005 ならばオプション設定で『マルチバイト文字セットを使用する』に
変更してみて下さい。多分、設定のせいです。
理由としてはプログラムが Unicode 文字を扱うように作られていた場合に fgets()
でファイルから読み込むとマルチバイト文字(シフトJIS文字)のために表示がおかしく
なると思います。これはテキストファイルが Unicode 文字ではないからです。
・設定を変更するには構造プロパティを開き→『全般』→『文字セット』の項目を
『マルチ バイト文字セットを使用する』にします。
でもちょっと気になるのが
>メッセージボックスの一回目は正しく"あいうえお"と表示されますが、
>二回目・三回目は文字化けしています。
↑
となっている点です。最初の一回目だけは正しく表示されるのか?不思議?
・あと MessageBox() の第4引数は NULL ではなく MB_OK 定数を使いましょう。
余談:
・fopen() 関数のオープン文字列で『rt』は『rb』に対してテキストモードを指定する
意味ですが昔、聞いた話ではどこかの処理系の拡張指定だったと思います。
なので普段テキストは『r』『w』『a』の指定で良いです。
バイナリは『b』を付けた『rb』『wb』『ab』と指定します。
・以上。
この回答への補足
VC++2005です。マルチバイト文字にすると一回目から文字化けしました。
情報が不足で申し訳ありません。
WindowsXP
Microsoft Visual Studio 2005 Academic Edition
テキストファイルはXPのメモ帳でUnicodeで保存。
プロジェクトオプション "Unicode文字セットを使用する"
ソースファイルの拡張子はcppでなくcにしています。
# fopenはrtにしても変わりませんでした。
# 一回目で文字化けすれば諦めてfgets以外の方法を探すのですが、
# 中途半端に上手くいくばっかりに困ってます・・
No.2
- 回答日時:
他人の回答にケチを付けるのは気が引けますし、禁止事項にも抵触するのでしょうが、放置しているわけにはいかないので指摘します。
> テキストファイルを読み込む場合は「"r"」ではなく「"rt"」で。
上記は嘘です。
> 「"r"」を指定した場合は「処理系依存」なので、もしバイナリで開かれた場合は改行文字が正しく処理できずfgetsは「動作結果は未定義」となります。
そんなことはありません。
むしろ、"rt"を指定した場合の動作が未定義になります。
> ※ライブラリ仕様の「動作結果は未定義」とは「バグるから何が起きるか予想できない」と言う意味です。
何が起きるか予想できないのはある意味その通りですが、必ずしも「バグる」わけではありません。
今回の件に関しては、標準規格でも、("rt"のような規定外の文字列を使用した場合には)「動作は未定義とする」としつつも、処理系は残りの文字の並び(今回でいえば"t")を無視してよいなどの具体例を挙げています。
No.1
- 回答日時:
>fopen("textlist.txt", "r")
テキストファイルを読み込む場合は「"r"」ではなく「"rt"」で。
fopen("textlist.txt", "rt")
「"r"」を指定した場合は「処理系依存」なので、もしバイナリで開かれた場合は改行文字が正しく処理できずfgetsは「動作結果は未定義」となります。
※ライブラリ仕様の「動作結果は未定義」とは「バグるから何が起きるか予想できない」と言う意味です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 3 2022/10/27 17:44
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- PHP 空文字 "" ですが 空文字の意味を教えてください。 3 2022/08/05 03:51
- その他(コンピューター・テクノロジー) 【Tableau Desktop】文字列から8桁の数字を日付型(yyyyMMdd)として取得 1 2023/07/31 10:17
- その他(データベース) Accessのクエリで1フィールドの抽出条件設定をNullでなく全角半角含む空白のみの文字列でない文 1 2023/04/24 15:20
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
このQ&Aを見た人はこんなQ&Aも見ています
-
【お題】NEW演歌
【大喜利】 若い人に向けたことは分かるけど、それはちょっと寄せ過ぎて変になってないか?と思った演歌の歌詞
-
家・車以外で、人生で一番奮発した買い物
どんなものにお金をかけるかは人それぞれの価値観ですが、 誰もが一度は清水の舞台から飛び降りる覚悟で、ちょっと贅沢な買い物をしたことがあるはず。
-
これ何て呼びますか Part2
あなたのお住いの地域で、これ、何て呼びますか?
-
おすすめのモーニング・朝食メニューを教えて!
コメダ珈琲店のモーニング ロイヤルホストのモーニング 牛丼チェーン店の朝食などなど、おいしいモーニング・朝食メニューがたくさんありますよね。
-
とっておきの「まかない飯」を教えて下さい!
飲食店で働く方だけが食べられる、とっておきの「まかない飯」。 働いてらっしゃる方がSNSなどにアップしているのを見ると、表のメニューには出てこない秘密感もあって、「食べたい!!」と毎回思ってしまいます。
-
fgetws関数で読み込んだUNICODE文字列の文字化け
C言語・C++・C#
-
fgets で値が取得できない
C言語・C++・C#
-
VC++でUTF-8のファイルを出力したい
C言語・C++・C#
-
-
4
C言語でUTF-8コードで読み込んで表示は日本語にしたい
C言語・C++・C#
-
5
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
6
csvファイルをfscanfで読み込むと変な文字が出てきます
C言語・C++・C#
-
7
fopenで別ディレクトリにファイルをオープンしたい
C言語・C++・C#
-
8
カンマ区切りのデータを配列に読み込みたい
C言語・C++・C#
-
9
C言語のポインターに関する警告
C言語・C++・C#
-
10
構造体のextern方法
C言語・C++・C#
-
11
ファイル書込みで一行もしくは部分的に上書きする
PHP
-
12
C言語で複数列のデータを1列のみ読み込みたい
C言語・C++・C#
-
13
多重定義が起きている?--lnk2005エラー:VC++
C言語・C++・C#
-
14
c言語でのfscanfについて
C言語・C++・C#
-
15
日本語が文字化けしないよう読み込み
PHP
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ハフマン符号のプログラム
-
fgetsで2行目から文字化け
-
fopen(書き込みモード)でファイ...
-
BCB 読み込み。
-
VBSで指定行に挿入
-
【VB.Net】バイト型配列に読み...
-
C言語 バイナリファイルの読み...
-
c言語 2つのファイルを行ご...
-
バイナリファイルをテキストフ...
-
C言語初心者の質問失礼します。
-
FTPでputすると空ファイルが出...
-
フルパスから最後のディレクト...
-
どんなプログラムを書いても指...
-
バッファとは何ですか
-
csvファイルを開かずに文字を検...
-
ファイル名の先頭にアンダース...
-
UTL_FILEにて既存のExcelに追加...
-
c/c++ ビルドしたにもかかわら...
-
VB.NETで他のプロジェクトで作...
-
ファイルの結合
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ファイル内のデータを1行削除...
-
テキストファイルの行数を取得...
-
バイナリファイルをテキストフ...
-
c言語 2つのファイルを行ご...
-
fgetsで2行目から文字化け
-
改行までの一文字ずつのファイ...
-
VBSで指定行に挿入
-
winsock recvでの文字化け
-
【VB.Net】バイト型配列に読み...
-
巨大なテキストファイル(可変...
-
C言語での改行コードの扱いにつ...
-
EOF判定されない
-
【C言語】テキスト読み込みの行...
-
続・EOF判定されない
-
freadでファイルを読み込んだ際...
-
fopenで開いたファイルのサイズ...
-
C言語 バイナリファイルの読み...
-
0x00をファイル出力
-
0バイトファイルの作成
-
ファイル読み込みについて
おすすめ情報