# 安裝 GFortran 使用 Fortran 程式讀取、寫入 csv 檔 > 作者:王一哲 > 日期:2021/7/31 <br /> ## 前言 我之前幾乎沒有寫過 Fortran,這次為了幫某人擺脫需要花錢購買的 [Visual Fortran](https://software.intel.com/content/www/us/en/develop/articles/intel-visual-fortran-compiler-190-for-windows-release-notes-for-intel-parallel-studio-xe-2019.html),我只好從零開始學 Fortran,並且試試看是否能用 [GFortran](https://gcc.gnu.org/wiki/GFortran) 編譯他們實驗室需要的程式碼,由 csv 檔讀取資料經過一些運算後再儲存成另一個 csv 檔,以下是我測試的筆記。 <br /> ## 於 Ubuntu 安裝 GFortran 我使用的作業系統是 Ubuntu 20.04.2 LTS,只要在文字界面中執行以下指令即可安裝 GFortran。 ```shell sudo apt install gfortran-10 ``` <br /> 安裝完畢之後可以用以下指令查詢安裝的版本,我安裝的版本是 10.3.0。 ```shell gfortran-10 --version ``` <br /> 建立一個測試用的資料夾,於資料夾中用文字編輯器將以下內容儲存成 hello.f95。 ```fortran program hello write(*, *) 'Hello World!' write(*, *) '哈囉世界!' stop end program hello ``` <br /> 用以下指令將 hello.f95 編譯成執行檔再執行檔案。 ```shell gfortran-10 -o hello hello.f95 ./hello ``` <br /> 如果螢幕輸出以下文字就成功了。 ```shell Hello World! 哈囉世界! ``` <br /> ## 於 Windows 10 安裝 GFortran 我使用的作業系統是 Windows 10 家用版。安裝步驟主要是參考這篇文章 [Installation of GFortran in Windows 10](https://masuday.github.io/fortran_tutorial/install_gfortran_windows.html)。先安裝 [mingw-w64](http://mingw-w64.org/doku.php),目前最新的版本是 msys2-x86_64-20210725.exe,[下載連結在此](https://github.com/msys2/msys2-installer/releases/download/2021-07-25/msys2-x86_64-20210725.exe)。安裝完成之後開啟 MSYS2 MinGW 64-bit。 <img height="40%" width="40%" src="https://i.imgur.com/xIlG034.png" style="display: block; margin-left: auto; margin-right: auto;"/> <div style="text-align:center">MSYS2</div> <br /><br /> 輸入以下指令更新軟體列表、安裝 GFortran。 ```shell pacman -Syu pacman -Su gcc-fortran ``` <br /> 輸入以下指令查詢安裝好的 GFortran 版本。 ```shell gfortran.exe --version ``` <br /> 我安裝的是 10.2.0 版。用 pwd 查詢路徑,看起來是在 /home/[UserName] 底下,實際上的路徑是 ```shell C:\msys64\home\[UserName] ``` <br /> 接著用 Hello World! 測試一下。 <img height="60%" width="60%" src="https://i.imgur.com/oMB3I1f.png" style="display: block; margin-left: auto; margin-right: auto;"/> <div style="text-align:center">於 Windows 10 測試 GFortran</div> <br /><br /> ## 使用 Fortran 程式讀取、寫入 csv 檔 這次的目標是要在執行程式時於後方加上輸入、輸出檔名,由輸入的 csv 檔讀取資料,再將資料寫到輸出的 csv 檔,主要是參考這兩個網頁的內容:[Passing command line arguments](https://riptutorial.com/fortran/example/26615/passing-command-line-arguments)、[TEK-TIPS.COM: Help with .csv](https://www.tek-tips.com/viewthread.cfm?qid=1710427)。假設輸入檔名為 input.csv,內容如下,第一行開頭的 ! 是為了在讀取資料時忽略此行而加上的記號。 ``` !h(m),t(s),errt(s) 2,0.65,0.01 4,0.89,0.01 6,1.11,0.01 8,1.27,0.01 10,1.42,0.01 12,1.57,0.01 14,1.71,0.01 16,1.79,0.01 18,1.92,0.01 20,2.03,0.01 ``` <br /> 以下是我測試成功的程式碼。 ```fortran= program fileIO implicit none ! 不使用預設變數名稱及種類對應關係 character(20) :: inputfile ! 輸入檔名用的變數 character(20) :: outputfile ! 輸出檔名用的變數 integer :: flag1, flag2, line_num ! 檔案狀態1、2, 行號 character(80) :: line ! 讀取的整行資料 real :: h, t, t2, errt ! 儲存資料的變數 ! 檢查輸入的參數是否為2個 if(command_argument_count().NE.2) then write(*,*) 'Error! Please enter the input and output file names.' stop end if ! 由輸入的參數取得輸入、輸出檔名 call get_command_argument(1, inputfile) call get_command_argument(2, outputfile) write(*,*) 'The input file name is: ', inputfile write(*,*) 'The output file name is: ', outputfile ! 由 inputfile 讀取資料, 準備寫入資料至 outputfile open(3, file=inputfile, status='old', action='read', iostat=flag1) open(4, file=outputfile, action='write', iostat=flag2) ! 檢查是否能開啟檔案 if(flag1 .NE. 0) then write(*, *) 'Cannot open input file!' go to 99 end if if(flag2 .NE. 0) then write(*, *) 'Cannot open output file!' go to 99 end if ! 於 outputfile 寫入欄位標題 write(4, *) '!h(m),t(s),t2(s2),errt(s)' line_num = 0 do ! 讀取整行資料並存入 line read(3, '(A)', end=99, iostat=flag1) line ! 若 flag1 不等於 0 則跳到 99 continue if(flag1 .NE. 0) then write(*, *) 'Cannot read data!' go to 99 end if ! 若 line 的開頭為 '!' 則不做任何事 if(adjustl(trim(line(1:1))) .EQ. '!') then cycle end if ! 將 line 的資料分別存入 h, t, errt, 計算 t^2, 存入 outputfile read(line, *) h, t, errt t2 = t**2 write(*, *) 'line ', line_num, ': ', h, t, t2, errt line_num = line_num + 1 write(4, *) h, ',', t, ',', t2, ',', errt end do 99 continue close(3) close(4) stop end program fileIO ``` <br /> 假設檔名是 fileIO.f95,在 Ubuntu 可以使用以下指令編譯程式。 ```fortran gfortran-10 -o fileIO fileIO.f95 ``` <br /> 在 Windows 10 可以使用以下指令編譯程式。 ```fortran gfortran.exe -o fileIO fileIO.f95 ``` <br /> 使用以下指令執行程式。 ```shell ./fileIO input.csv output.csv ``` <br /> 於文字界面輸出以下的內容。 ```shell The input file name is: input.csv The output file name is: output.csv line 0 : 2.00000000 0.649999976 0.422499955 9.99999978E-03 line 1 : 4.00000000 0.889999986 0.792099953 9.99999978E-03 line 2 : 6.00000000 1.11000001 1.23210001 9.99999978E-03 line 3 : 8.00000000 1.26999998 1.61289990 9.99999978E-03 line 4 : 10.0000000 1.41999996 2.01639986 9.99999978E-03 line 5 : 12.0000000 1.57000005 2.46490026 9.99999978E-03 line 6 : 14.0000000 1.71000004 2.92410016 9.99999978E-03 line 7 : 16.0000000 1.78999996 3.20409989 9.99999978E-03 line 8 : 18.0000000 1.91999996 3.68639994 9.99999978E-03 line 9 : 20.0000000 2.02999997 4.12089968 9.99999978E-03 ``` <br /> <img height="100%" width="100%" src="https://i.imgur.com/CBjWRKC.png" style="display: block; margin-left: auto; margin-right: auto;"/> <div style="text-align:center">於 Windows 10 測試 fileIO 程式碼</div> <br /><br /> 輸出的 csv 檔如下,看來應該有達到我要的效果。 ```shell !h(m),t(s),t2(s2),errt(s) 2.00000000 , 0.649999976 , 0.422499955 , 9.99999978E-03 4.00000000 , 0.889999986 , 0.792099953 , 9.99999978E-03 6.00000000 , 1.11000001 , 1.23210001 , 9.99999978E-03 8.00000000 , 1.26999998 , 1.61289990 , 9.99999978E-03 10.0000000 , 1.41999996 , 2.01639986 , 9.99999978E-03 12.0000000 , 1.57000005 , 2.46490026 , 9.99999978E-03 14.0000000 , 1.71000004 , 2.92410016 , 9.99999978E-03 16.0000000 , 1.78999996 , 3.20409989 , 9.99999978E-03 18.0000000 , 1.91999996 , 3.68639994 , 9.99999978E-03 20.0000000 , 2.02999997 , 4.12089968 , 9.99999978E-03 ``` <br /> ## 結語 由於 Fortran 的語法與 Python、C、C++ 差異很大,寫起來感覺相當奇怪。接下來還要再修改他們實驗室以前的程式碼,其中一部分還是採用 Fortran 77 的語法撰寫,要修改成新版 GFotrtan 可以接受的語法才行,好像還有不少的麻煩要解決。 <br /> ## 參考資料 1. [gfortran — the GNU Fortran compiler, part of GCC](https://gcc.gnu.org/wiki/GFortran) 2. [Installation of GFortran in Windows 10](https://masuday.github.io/fortran_tutorial/install_gfortran_windows.html) 3. [mingw-w64](http://mingw-w64.org/doku.php) 4. [Passing command line arguments](https://riptutorial.com/fortran/example/26615/passing-command-line-arguments) 5. [TEK-TIPS.COM: Help with .csv](https://www.tek-tips.com/viewthread.cfm?qid=1710427) <br /> --- ###### tags:`Computer`、`Fortran`