
C言語でファイルを読み書きする方法を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Verse(UEFN), Assembler (x64,aarch64).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信や,Unreal Editor for Fortnite(UEFN)でゲーム開発に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でChatGPT/Geminiを訓練するプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
- UEFNで10本以上のゲームを開発し,フォートナイト上で公開(Fortnite,Fortnite.GG).
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
fopen関数
| 1 | FILE *fopen(const char *pathname, const char *mode); | 
fopen関数は,ファイルを操作するANSI規格の関数です.
第1引数のpathnameで指定された名前のファイルを第2引数のmodeで開き,ストリームと結びつけます.
| 1 | int fclose(FILE *stream); | 
fclose関数は,streamが指すストリームを(バッファーリングされて いた全ての出力データをfflush関数を用いて書き込んで)フラッシュし,対応するファイルディスクリプタをクローズする関数です.
fopen関数とペアで利用します.
fopen関数でファイルの読み込み
fopen関数でファイルの読み込みをするコードは以下になります.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> #define FILENAME "fopen.c" int main(void) {   int c;   FILE *fp;   if ((fp = fopen(FILENAME, "r")) == NULL) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   while ((c = fgetc(fp)) != EOF) {     putchar(c);   }   if (fclose(fp) == EOF) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(2);   }   return 0; } | 
実行結果は以下になります.
fopen.cの中身を表示していることがわかります.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | $ gcc fopen.c $ a.out  /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> #define FILENAME "fopen.c" int main(void) {   int c;   FILE *fp;   if ((fp = fopen(FILENAME, "r")) == NULL) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   while ((c = fgetc(fp)) != EOF) {     putchar(c);   }   if (fclose(fp) == EOF) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(2);   }   return 0; } | 
fopen関数でファイルの書き込み
fopen関数でファイルの書き込みをするコードは以下になります.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> #define FILENAME "output.txt" #define STR "fopen2.c\n" int main(void) {   FILE *fp;   if ((fp = fopen(FILENAME, "w")) == NULL) {     fprintf(stderr, "Error cannot open %s.\n", FILENAME);     exit(1);   }   fprintf(fp, STR);   if (fclose(fp) == EOF) {     fprintf(stderr, "Error: cannot close %s.\n", FILENAME);     exit(2);   }   return 0; } | 
実行結果は以下になります.
3行目のcat output.txtで「fopen2.c」と表示されるので,9行目で定義したSTRが正しく書き込まれていることがわかります.
| 1 2 3 4 | $ gcc fopen2.c  $ a.out  $ cat output.txt  fopen2.c | 
open関数
| 1 | int open(const char *pathname, int flags); | 
open関数は,ファイルのオープンと作成を行うPOSIX.1-2008規格の関数です.
第1引数のpathnameにファイルを指定し,第2引数のflagsにアクセスモードを設定します.
flagsには,アクセスモード O_RDONLY,O_WRONLY,O_RDWRのどれか1つを含まなければなりません.
それぞれ,読み込み専用,書き込み専用,読み書き用にファイルをオープンします.
open関数は,LinuxのGCC/Clangコンパイラで利用できますが,Visual Studioで利用できないことに注意して下さい.
open関数は,fopen関数の中で呼び出されます.
fopen関数とは異なり,open関数はバッファがないので,データをすぐに読み書きできます.
fopen関数は標準出力(バッファあり),open関数は標準エラー出力(バッファなし)の関係と似ています.
標準出力と標準エラー出力の違いを知りたいあなたはこちらからどうぞ.
| 1 | int close(int fd); | 
close関数は,ファイルディスクリプタfdをクローズする関数です.
open関数とペアで利用します.
open関数でファイルの読み込み
open関数でファイルの読み込みをするコードは以下になります.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define FILENAME "open.c" int main(void) {   int c;   int fd;   if ((fd = open(FILENAME, O_RDONLY)) == -1) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   while (read(fd, &c, sizeof(char)) > 0) {     putchar(c);   }   if (close(fd) == -1) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(2);   }   return 0; } | 
実行結果は以下になります.
open.cの中身を表示していることがわかります.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | $ gcc open.c  $ a.out  /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define FILENAME "open.c" int main(void) {   int c;   int fd;   if ((fd = open(FILENAME, O_RDONLY)) == -1) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   while (read(fd, &c, sizeof(char)) > 0) {     putchar(c);   }   if (close(fd) == -1) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(2);   }   return 0; } | 
open関数でファイルの書き込み
open関数でファイルの書き込みをするコードは以下になります.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define FILENAME "output.txt" #define STR "open2.c\n" int main(void) {   int fd;   if ((fd = open(FILENAME, O_WRONLY | O_CREAT)) == -1) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   write(fd, STR, sizeof(STR));   if (close(fd) == -1) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(2);   }   return 0; } | 
実行結果は以下になります.
3行目のcat output.txtで「open2.c」と表示されるので,13行目で定義したSTRが正しく書き込まれていることがわかります.
| 1 2 3 4 | $ gcc open2.c  $ a.out  $ cat output.txt  open2.c | 
fopen_s関数
| 1 | errno_t fopen_s(FILE** pFile, const char *filename, const char *mode); | 
fopen_s関数は,fopen関数にセキュリティ機能を追加したC11規格の関数です.
fopen関数とは異なり,fopen_s関数は,複数のプログラムから同時に同じファイルをオープンできません(排他モードでオープンします).
排他モードでオープンすることにより,ファイルの中身が処理系定義の動作にならないことが保証されます.
fopen_s関数は,きちんとエラーチェックが出てくれるので,バグが発見しやすくて嬉しいですよね.
fopen関数と同様に,fopen_s関数でオープンしたファイルをクローズする時は,fclose関数を利用します.
また,fopen_s関数は,Visual Studioで利用できますが,LinuxのGCC/Clangコンパイラで利用できないことに注意して下さい.
fopen_s関数とfopen関数のエラー検出の違いは以下になります.
- fopen_s関数のエラー検出
- 返り値のerrno_tが0
- 第2引数で渡したファイルポインタがNULL
 
- fopen関数のエラー検出
- 返り値のFILEポインタがNULL
 
つまり,fopen_s関数は2重でエラー検出ができます.
fopen_s関数でファイルの読み込み
fopen_s関数でファイルの読み込みをするコードは以下になります.
9行目のFILENAMEはあなたの環境で変更して下さい(usernameやファイル名等).
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> /* Please change FILENAME for your environment. */ #define FILENAME "C:\\Users\\username\\Desktop\\output.txt" int main(void) {   int c;   FILE *fp;   errno_t errno;   if ((errno = fopen_s(&fp, FILENAME, "r")) != 0) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   if (fp == NULL) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(2);   }   while ((c = fgetc(fp)) != EOF) {     putchar(c);   }   if (fclose(fp) == EOF) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(3);   }   return 0; } | 
Visual Studioでの実行結果は以下になります.
output.txtの中身「fopen_s.c」を表示できていることがわかります.
| 1 2 3 4 | fopen_s.c *.exe (プロセス *) は、コード 0 で終了しました。 このウィンドウを閉じるには、任意のキーを押してください... | 
fopen_s関数でファイルの書き込み
fopen_s関数でファイルの書き込みをするコードは以下になります.
9行目のFILENAMEはあなたの環境で変更して下さい(usernameやファイル名等).
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /*  * Author: Hiroyuki Chishiro  * License: 2-Clause BSD  */ #include <stdio.h> #include <stdlib.h> /* Please change FILENAME for your environment. */ #define FILENAME "C:\\Users\\username\\Desktop\\output.txt" #define STR "fopen_s2.c" int main(void) {   FILE *fp;   errno_t errno;   if ((errno = fopen_s(&fp, FILENAME, "w")) != 0) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(1);   }   if (fp == NULL) {     fprintf(stderr, "Error: cannot open \"%s\".\n", FILENAME);     exit(2);   }   fprintf(fp, STR);   if (fclose(fp) == EOF) {     fprintf(stderr, "Error: cannot close \"%s\".\n", FILENAME);     exit(3);   }   return 0; } | 
Visual Studioでの実行結果は以下になります.
同じディレクトリにあるoutput.txtを確認してみると,output.txtの中身が「fopen_s2.c」になっていることがわかります.
| 1 2 | *.exe (プロセス *) は、コード 0 で終了し ました。 このウィンドウを閉じるには、任意のキーを押してください... | 
まとめ
C言語でfopen/open/fopen_s関数の使い方を紹介しました.
具体的には,fopen/open/fopen_s関数でファイルを読み書きするコードを説明しました.
fopen/open/fopen_s関数の違いをまとめると下表になります.
| 項目 | fopen関数 | open関数 | fopen_s関数 | 
|---|---|---|---|
| 規格 | ANSI C | POSIX.1-2008 | C11 | 
| 実行可能なコンパイラ・開発環境 | GCC/Clang/Visual Studio | GCC/Clang | Visual Studio | 
| エラー検出 | 返り値(ファイルポインタ) | 返り値(ファイルディスクリプタ) | 返り値(errno_t) 第1引数(ファイルポインタ) | 
| 排他モードでオープン | できない | できない | できる | 
| クローズする時に使う関数 | fclose関数 | close関数 | fclose関数 | 
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!


