C/C++ 文件讀寫


 

•前言

  第一次接觸文件讀寫是在大一的C語言教材中,當時哼哧吧唧的學的賊費勁,雖然最后也學會了,但好像沒怎么用過。

  在后來,就是在OJ上刷題的時候,編寫的代碼有時候連樣例都不能通過;

  這個時候就需要各種修改,然后各種輸入樣例,調試起來顯得很費力,差不多這個時候,才正式開始使用文件讀寫。

  體驗真的棒~~

•C中的文件讀寫-freopen

函數簡介

  freopen  是被包含於 C標准庫頭文件  stdio.h  中的一個函數,用於重定向輸入輸出流。

  該函數可以在不改變代碼原貌的情況下改變輸入輸出環境,但使用時應當保證流是可靠的。

函數聲明

 *FILE freopen(const char* _FileName, const char* _Mode, FILE* _Stream ); 

  • _FileName:需要重定向的文件名或文件路徑
  • _Mode:代表文件訪問權限的字符串
    • "r" 表示 只讀訪問
    • "w" 表示 只寫訪問
    • "a" 表示 追加寫入
  • _Stream:需要被重定向的文件流
    • stdin:表示輸入重定向(從指定文件中讀取數據到程序中)
    • stdout:表示輸出重定向(將程序中輸出的數據輸入到指定文件中)
  • 返回值:如果成功,則返回指向該輸出流的文件指針,否則返回為NULL

測試輸出重定向(寫文件)

  新建一個項目,並命名為文件讀寫;

  在該項目中創建一個  C中的文件讀寫.c  文件,並添加如下代碼:

#include<stdio.h>
#define FILENAME "FILEC.txt"//文件名

void write()
{
    freopen(FILENAME, "w", stdout);

    printf("測試向FILEC.txt中寫文件\n");
}
int main()
{
    write();

    return 0;
}

  運行該代碼,你會發現,在項目文件讀寫的文件夾下多出一個  FILEC.txt 的文件,打開該文件,你會驚奇的發現,該文件的內容就是你在程序中通過 printf 輸出的語句。

  通過代碼可以看出,freopen 函數只出現在了  write() 函數中,那么如果在主函數中輸出 "Hello World",會輸出到哪里呢?

  讓我們通過代碼來測試一下。

void write()
{
    freopen(FILENAME, "w", stdout);

    printf("測試向FILEC.txt中寫文件\n");
}
int main()
{
    printf("TEST1 : Hello World\n");
    write();
    printf("TEST2 : Hello World\n");

    return 0;
}

  運行該代碼,你會發現,在控制台只輸出了 "TEST1 : Hello World":

  少的那一句呢?

  莫非是輸出到 FILEC.txt  中了,讓我們一探究竟。

  果然在這里,通過這個測試,就能發現,在語句  freopen(FILENAME, "w", stdout); 調用后,所有的輸出語句都寫到了  FILEC.txt 中。

  C 語言中提供了文件讀寫的關閉語句  fclose(stdout) ,那可不可以通過該語句實現隨開隨關呢?

  讓我們嘗試在  write() 中使用該語句。

void write()
{
    freopen(FILENAME, "w", stdout);

    printf("測試向FILEC.txt中寫文件\n");

    fclose(stdout);
}
int main()
{
    printf("TEST1 : Hello World\n");
    write();
    printf("TEST2 : Hello World\n");

    return 0;
}

  讓我們來運行一下修改后的程序。

運行結果

  在 VS2022 上,直接報錯了:

  而在 CodeBlocks 中測試,成功運行了:

  但是, FILEC.txt 文件中卻丟失了  printf("TEST2 : Hello World\n"); 語句的輸出結果:

  所以,通過測試可知,並不能通過  fclose(stdout); 語句實現隨開隨關 ,正確的寫法應該是:

#include<stdio.h>
#define FILENAME "FILEC.txt"//文件名

void write()
{
    freopen(FILENAME, "w", stdout);

    printf("測試向FILEC.txt中寫文件\n");
}
int main()
{
    printf("TEST1 : Hello World\n");

    write();

    printf("TEST2 : Hello World\n");

    fclose(stdout);//放置到程序結尾處
    return 0;
}

測試輸入重定向(讀文件)

  在程序所在目錄下新建一個 Input.txt 文件,並輸入如下信息:

  運行如下代碼:

#include<stdio.h>
#define FILENAME "Input.txt"

int main()
{
    freopen(FILENAME,"r",stdin);//讀文件
    
    char s[100];
    while (scanf("%s", s) != EOF)
        puts(s);
    
    return 0;
}

  運行該程序,你會發現,並不需要輸入任何數據:

  控制台輸出的內容剛好是  Input.txt  中的內容。

  • scanf("%s", s) != EOF 表示的是讀取到文件結尾
  • FILENAME 也可以換成 Input.txt 的具體路徑 

 E:\\Documents\\Visual Studio for C++\\文件讀寫\\文件讀寫\\Input.txt 

  • 其中,路徑中的 "\\" 可以換成 '/',但不能是 '\'

  同理,我們也可以用  fclose(stdin); 來關閉該輸入流,但同輸出流一樣,應該放到程序結尾出:

#include<stdio.h>
#define FILENAME "Input.txt"

int main()
{
    freopen(FILENAME,"r",stdin);//讀文件
    
    char s[100];
    while (scanf("%s", s) != EOF)
        puts(s);
    
    fclose(stdin);//放到程序結尾處
    return 0;
}

•C++中的文件讀寫-fstream

函數簡介

  C++中對文件操作需要包含頭文件  <fstream> (file stream,文件流)。

  • ofstream:寫操作(output file stream)
  • ifstream: 讀操作(input file stream)
  • fstream : 讀寫操作(file stream)

寫文件

步驟

  • 創建流對象:ofstream ofs; 
  • 打開文件:ofs.open("文件名/文件路徑",打開方式);
  • 寫數據:ofs << "寫入的數據"; (將 cout 改為 ofs)
  • 關閉文件:ofs.close(); 

文件打開方式

  •  ios::out :為寫文件而打開文件
  •  ios::app :追加方式寫文件

  在代碼所在的文件夾下新建一個  FILEC++.txt 文件,添加如下數據:

  並運行如下代碼:

#include<iostream>
#include<fstream>//包含頭文件
using namespace std;
#define FILENAME "FILEC++.txt"

void write()
{
    ofstream ofs;//創建流對象
    ofs.open(FILENAME, ios::out);//打開文件

    ofs << "測試向FILEC++.txt中寫文件" << endl;//寫數據

    ofs.close();//關閉文件
}
int main()
{
    write();

    return 0;
}

  打開  FILEC++.txt 查看文件內容變化。

  你會發現,通過  ios::out 方式打開文件,之前的內容被覆蓋了。

  更改文件打開方式:

void write()
{
    ofstream ofs;//創建流對象
    ofs.open(FILENAME, ios::app);//打開文件

    ofs << "測試向FILEC++.txt中寫文件-2.0" << endl;//寫數據

    ofs.close();//關閉文件
}

  查看  FILEC++.txt 中的內容:

  可以測試出, ios::app 是在原文件的基礎上向后追加內容。

  由於是通過創建  ofs 來進行寫文件操作,那么原本的輸出語句就不會報錯。

#include<iostream>
#include<fstream>//包含頭文件
using namespace std;
#define FILENAME "FILEC++.txt"

void write()
{
    ofstream ofs;//創建流對象
    ofs.open(FILENAME, ios::out);//打開文件

    ofs << "測試向FILEC++.txt中寫文件" << endl;//寫數據

    ofs.close();//關閉文件
}
int main()
{
    cout << "TEST1 : Hello World" << endl;
    write();
    cout << "TEST2 : Hello World" << endl;
    return 0;
}

  運行結果:

   FILEC++.txt :

  可見,通過  ofstream 來進行寫文件操作,並不會影響  cout 的輸出。

讀文件

步驟

  • 創建流對象: ifstream ifs; 
  • 打開文件: ifs.open("文件路徑",打開方式); 
  • 判斷文件是否打開成功: ifs.is_open() (成功打開返回 true,否則返回 false)
  • 讀數據: ifs >> 變量1 >> 變量2 >> ...; (類比 cin)
  • 關閉文件: ifs.close(); 

示例

  在當前代碼所在文件夾下新建一個  Input.txt 的文件,並放入如下數據:

  分別代表:編號、姓名、年齡,並用 id , name , age 接受這三個數據。

#include<iostream>
#include<fstream>//包含頭文件
using namespace std;
#define FILENAME "Input.txt"

void read()
{
    ifstream ifs;//創建流對象
    ifs.open(FILENAME, ios::in);//打開文件

    int id;
    string name;
    int age;

    if (!ifs.is_open())//判斷文件是否打開成功
    {
        cout << "文件打開失敗" << endl;
        return;
    }

    ifs >> id >> name >> age;//讀數據,且 編號、姓名、年齡 要和文件中的數據保持一致
    cout << "編號\t姓名\t年齡" << endl;
    cout << id << "\t" << name << "\t" << age << endl;

    ifs.close();//關閉文件

    return;
}
int main()
{
    read();

    return 0;
}

  運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM