0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ファイル入出力に現れるminGWとCygwinの設計思想の違い

Posted at

Windows環境で書かれたC言語のプログラムをレビューする1機会があり、そこでファイル入出力に関しての面白い知見が得られたので記録を残しておく。

前提

  • 筆者自身はMacユーザであり、Windowsには明るくない

環境

  • Parallels Desktop 15上の仮想環境として動作させたWindows 10 Pro (Ver. 1909)
  • MSYS2 (20200602.0.0)
  • Cygwin (3.1.5)
  • 上記2つはchocolatey経由でインストール

TL;DR

MinGWはWindows環境の実装としてファイル入出力時にテキストモードとバイナリモードを区別する一方で、CygwinはLinux環境の再現としてファイル入出力時に2つのモードを区別しない。

ファイル入出力時の動作の違い

  • 検証用のコード
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {
  int count = 0;
  char c;
  FILE *fp;

  int binary_mode = 0;
  if (argc > 1 && strcmp(argv[1], "-b") == 0) {
    binary_mode++; // "-b"オプションでバイナリモードでのファイル読み込みを指定
  }
  
  int i;
  for (i = 1 + binary_mode; i < argc; i++) {
    if ((fp = fopen(argv[i], (binary_mode > 0) ? "rb" : "r")) == NULL) {
      printf("Error reading file");
      return 1;
    }
    
    count = 0;
    while ((c = fgetc(fp)) != EOF) {
      count++;
      if (c == '\r') {
        printf("%6d: <CR>\n", count);
      } else if (c == '\n') {
        printf("%6d: <LF>\n", count);
      } else {
        printf("%6d: %c\n", count, c);
      }
    }
  
    fclose(fp);

    printf("[%s] contains %d characters\n", argv[i], count);
  }
  
  return 0;
}
  • 検証用ファイル

<CR>はキャリッジリターン(0x0D)、<LF>はラインフィード(0x0A)を表す。

cr.txt
CR<CR>
lf.txt
LF<LF>
crlf.txt
CRLF<CR><LF>

MinGW(MSYS2)上の挙動

$ gcc -o test-mingw test.c
$ ./test-mingw.exe cr.txt lf.txt crlf.txt
     1: C
     2: R
     3: <CR>
[cr.txt] contains 3 characters
     1: L
     2: F
     3: <LF>
[lf.txt] contains 3 characters
     1: C
     2: R
     3: L
     4: F
     5: <LF>
[crlf.txt] contains 5 characters

$ ./test-mingw.exe -b cr.txt lf.txt crlf.txt
     1: C
     2: R
     3: <CR>
[cr.txt] contains 3 characters
     1: L
     2: F
     3: <LF>
[lf.txt] contains 3 characters
     1: C
     2: R
     3: L
     4: F
     5: <CR>
     6: <LF>
[crlf.txt] contains 6 characters

MinGWではファイル読み込みにテキストモードを指定した場合とバイナリモードを指定した場合で結果が異なる。
テキストモードを指定した場合、<CR>単体や<LF>単体はそのまま1文字として読み込まれる一方で、<CR><LF><LF>1文字に変換されて読み込まれる。

Cygwin上の挙動

$ gcc -o test-cygwin test.c
$ ./test-cygwin.exe cr.txt lf.txt crlf.txt
     1: C
     2: R
     3: <CR>
[cr.txt] contains 3 characters
     1: L
     2: F
     3: <LF>
[lf.txt] contains 3 characters
     1: C
     2: R
     3: L
     4: F
     5: <CR>
     6: <LF>
[crlf.txt] contains 6 characters

$ ./test-cygwin.exe -b cr.txt lf.txt crlf.txt
     1: C
     2: R
     3: <CR>
[cr.txt] contains 3 characters
     1: L
     2: F
     3: <LF>
[lf.txt] contains 3 characters
     1: C
     2: R
     3: L
     4: F
     5: <CR>
     6: <LF>
[crlf.txt] contains 6 characters

テキストモードかバイナリモードかにかかわらず、1バイト単位で文字が読み込まれる。

MinGWとCygwinの設計思想

MinGWのWebサイトには以下の記述がある:

MinGW, a contraction of "Minimalist GNU for Windows", is a minimalist development environment for native Microsoft Windows applications.
(中略)
MinGW, being Minimalist, does not, and never will, attempt to provide a POSIX runtime environment for POSIX application deployment on MS-Windows.

つまり、MinGWはあくまでもWindowsネイティブアプリケーションのための開発環境を提供しているため、Windows特有のファイルモードに対応しているといえる。

一方で、CygwinのWebサイトには以下の記述がある:

Cygwin is:

  • a large collection of GNU and Open Source tools which provide functionality similar to a Linux distribution on Windows.

したがって、CygwinはLinux環境をWindows上で再現するものであるため、Windows特有のファイルモードに対応せずにLinux環境同様すべてのファイルを一元的に扱っているといえる。

参考文献

初心者のためのポイント学習C言語 第17章 ファイル入出力

  1. 要はTAとして採点作業しただけである。ものは言いよう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?