深入理解Linux文件操作:stdin/stdout/stderr與C語言文件函數全解析

目錄

一、stdin、stdout 和 stderr 詳解

二、文件打開方式

三、C語言文件操作函數詳解

1、文件操作概述

2、文件操作函數分類表

1. 文件打開與關閉

2. 字符讀寫函數

3. 字符串讀寫函數

4. 格式化讀寫函數

5. 二進制讀寫函數

6. 文件定位函數

7. 文件狀態與錯誤檢測

8. 其他文件操作函數

3、注意事項

4、對文件進行寫入操作示例

5、對文件進行讀取操作示例

6、另一個讀文件的例子

代碼功能

代碼結構分析

1. 代碼功能

2. 代碼解析

(1) 參數檢查

(2) 打開文件

(3) 讀取文件內容

(4) 關閉文件

3. 關鍵點分析

(1)?fread?的返回值

(2)?buf[s] = '\0'?的作用

(3) 循環終止條件

四、輸出信息到顯示器的常用方法

1、代碼功能

2、代碼解析

(1)?fwrite?方式

(2)?printf?方式

(3)?fprintf?方式

3、輸出結果

4、關鍵區別

5、使用場景建議

6. 擴展:puts?和?fputs

7. 總結

五、?什么是當前路徑?

命令解析:ps -axj | head -1 && ps -axj | grep demol | grep -v grep

組合效果:


一、stdin、stdout 和 stderr 詳解

????????在Linux系統中,"一切皆文件"的理念意味著所有設備都可以被視為文件進行操作。顯示器作為輸出設備被抽象為文件,通過寫入數據實現內容顯示;鍵盤作為輸入設備同樣被抽象為文件,系統通過讀取該文件獲取用戶輸入的字符。

????????這些特殊設備文件之所以不需要手動打開,是因為每個進程在創建時都會自動打開三個標準I/O流:

  1. 標準輸入(stdin) - 對應鍵盤設備
  2. 標準輸出(stdout) - 對應顯示器設備
  3. 標準錯誤(stderr) - 同樣對應顯示器設備

????????根據man手冊的說明,這三個標準流在C語言中都是以FILE*指針形式存在的,與 fopen 返回的文件指針類型相同。這種設計使得進程可以直接使用這些預打開的文件描述符進行基本輸入輸出操作,無需額外的打開步驟。

????????當運行C程序時,操作系統會自動使用C語言接口打開這三個標準輸入輸出流,這樣我們才能調用scanf和printf等函數進行鍵盤輸入和屏幕輸出。

????????實際上,stdin、stdout和stderr與通過fopen獲取的文件指針本質相同。例如使用fputs函數時,若將第二個參數設為stdout,函數就會直接將數據輸出到顯示器上。

#include <stdio.h>
int main()
{fputs("hello stdin\n", stdout);fputs("hello stdout\n", stdout);fputs("hello stderr\n", stdout);return 0;
}

此時我們相當于使用fputs函數向“顯示器文件”寫入數據,也就是顯示到顯示器上:?

????????需要注意的是,標準輸入流、標準輸出流和標準錯誤流并非C語言獨有的概念。在C++中對應的是cin、cout和cerr,幾乎所有編程語言都具備類似的設計。實際上,這些特性并非源于特定編程語言,而是由操作系統底層提供的基礎支持。


二、文件打開方式

文件操作模式說明:

  • r:以只讀方式打開文本文件。文件指針位于文件開頭。
  • r+:以讀寫方式打開文件。文件指針位于文件開頭。
  • w:以寫入方式打開文件。若文件存在則清空內容,不存在則創建新文件。文件指針位于文件開頭。
  • w+:以讀寫方式打開文件。若文件不存在則創建,存在則清空內容。文件指針位于文件開頭。
  • a:以追加方式打開文件(寫入內容到文件末尾)。若文件不存在則創建。文件指針位于文件末尾。
  • a+:以讀寫和追加方式打開文件。若文件不存在則創建。讀取時文件指針位于開頭,寫入時始終追加到末尾。

我將會在另一篇博客中詳細驗證上面的每一種文件打開模式,挺多內容的其實!!!


三、C語言文件操作函數詳解

1、文件操作概述

????????在C語言中,文件操作主要通過標準庫中的文件I/O函數實現。這些函數定義在<stdio.h>頭文件中。文件操作通常包括打開、讀寫、定位和關閉等基本操作。

2、文件操作函數分類表

1. 文件打開與關閉

函數原型功能描述參數說明返回值示例
FILE *fopen(const char *filename, const char *mode);打開文件filename: 文件名
mode: 打開模式
成功: 返回FILE指針
失敗: 返回NULL
FILE *fp = fopen("test.txt", "r");
int fclose(FILE *stream);關閉文件stream: 文件指針成功: 返回0
失敗: 返回EOF
fclose(fp);

文件打開模式:(同第六點)

  • "r": 只讀

  • "w": 只寫(創建新文件或清空已有文件)

  • "a": 追加

  • "r+": 讀寫(文件必須存在)

  • "w+": 讀寫(創建新文件或清空已有文件)

  • "a+": 讀寫(追加)

2. 字符讀寫函數

函數原型功能描述參數說明返回值示例
int fgetc(FILE *stream);從文件讀取一個字符stream: 文件指針成功: 返回讀取的字符
失敗/EOF: 返回EOF
char c = fgetc(fp);
int fputc(int c, FILE *stream);向文件寫入一個字符c: 要寫入的字符
stream: 文件指針
成功: 返回寫入的字符
失敗: 返回EOF
fputc('A', fp);
int getc(FILE *stream);同fgetc,但可能實現為宏同fgetc同fgetcchar c = getc(fp);
int putc(int c, FILE *stream);同fputc,但可能實現為宏同fputc同fputcputc('B', fp);

3. 字符串讀寫函數

函數原型功能描述參數說明返回值示例
char *fgets(char *s, int size, FILE *stream);從文件讀取一行s: 存儲緩沖區
size: 緩沖區大小
stream: 文件指針
成功: 返回s
失敗/EOF: 返回NULL
fgets(buf, 100, fp);
int fputs(const char *s, FILE *stream);向文件寫入字符串s: 要寫入的字符串
stream: 文件指針
成功: 返回非負值
失敗: 返回EOF
fputs("Hello", fp);

4. 格式化讀寫函數

函數原型功能描述參數說明返回值示例
int fprintf(FILE *stream, const char *format, ...);格式化輸出到文件stream: 文件指針
format: 格式字符串
...: 可變參數
成功: 返回寫入字符數
失敗: 返回負值
fprintf(fp, "%d %f", i, f);
int fscanf(FILE *stream, const char *format, ...);從文件格式化輸入stream: 文件指針
format: 格式字符串
...: 可變參數
成功: 返回匹配項數
失敗/EOF: 返回EOF
fscanf(fp, "%d %f", &i, &f);

5. 二進制讀寫函數

函數原型功能描述參數說明返回值示例
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);從文件讀取二進制數據ptr: 數據存儲位置
size: 每個元素大小
nmemb: 元素數量
stream: 文件指針
返回成功讀取的元素數fread(&data, sizeof(data), 1, fp);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);向文件寫入二進制數據ptr: 要寫入的數據
size: 每個元素大小
nmemb: 元素數量
stream: 文件指針
返回成功寫入的元素數fwrite(&data, sizeof(data), 1, fp);

6. 文件定位函數

函數原型功能描述參數說明返回值示例
int fseek(FILE *stream, long offset, int whence);移動文件位置指針stream: 文件指針
offset: 偏移量
whence: 起始位置(SEEK_SET/SEEK_CUR/SEEK_END)
成功: 返回0
失敗: 返回非0
fseek(fp, 0, SEEK_END);
long ftell(FILE *stream);獲取文件當前位置stream: 文件指針成功: 返回當前位置
失敗: 返回-1L
long pos = ftell(fp);
void rewind(FILE *stream);重置文件位置到開頭stream: 文件指針rewind(fp);
int fgetpos(FILE *stream, fpos_t *pos);獲取文件位置stream: 文件指針
pos: 存儲位置
成功: 返回0
失敗: 返回非0
fgetpos(fp, &pos);
int fsetpos(FILE *stream, const fpos_t *pos);設置文件位置stream: 文件指針
pos: 要設置的位置
成功: 返回0
失敗: 返回非0
fsetpos(fp, &pos);

7. 文件狀態與錯誤檢測

函數原型功能描述參數說明返回值示例
int feof(FILE *stream);檢測文件結束標志stream: 文件指針到達文件尾: 返回非0
否則: 返回0
while(!feof(fp)) {...}
int ferror(FILE *stream);檢測文件錯誤stream: 文件指針發生錯誤: 返回非0
否則: 返回0
if(ferror(fp)) {...}
void clearerr(FILE *stream);清除錯誤標志stream: 文件指針clearerr(fp);

8. 其他文件操作函數

函數原型功能描述參數說明返回值示例
int remove(const char *filename);刪除文件filename: 文件名成功: 返回0
失敗: 返回-1
remove("temp.txt");
int rename(const char *old, const char *new);重命名文件old: 原文件名
new: 新文件名
成功: 返回0
失敗: 返回-1
rename("old.txt", "new.txt");
FILE *tmpfile(void);創建臨時文件成功: 返回FILE指針
失敗: 返回NULL
FILE *tmp = tmpfile();
char *tmpnam(char *s);生成唯一文件名s: 存儲緩沖區(可為NULL)返回指向文件名的指針char name[L_tmpnam]; tmpnam(name);

3、注意事項

  1. 使用文件操作函數時,應始終檢查返回值以確保操作成功

  2. 打開文件后,必須記得關閉文件(重要!!!)

  3. 二進制模式和文本模式在Windows平臺上有區別(換行符處理不同)

  4. 文件指針位置會影響讀寫操作的結果

  5. 緩沖區內容在文件關閉或調用fflush()之前可能不會實際寫入磁盤

4、對文件進行寫入操作示例

#include <stdio.h>
int main()
{FILE* fp = fopen("log.txt", "w");if (fp == NULL){perror("fopen");return 1;}int count = 5;while (count){fputs("hello world\n", fp);count--;}fclose(fp);return 0;
}

編譯并運行程序后,在當前路徑下就會生成對應文件,文件當中就是我們寫入的內容:

5、對文件進行讀取操作示例

#include <stdio.h>
int main()
{FILE* fp = fopen("log.txt", "r");if (fp == NULL){perror("fopen");return 1;}char buffer[64];for (int i = 0; i < 5; i++){fgets(buffer, sizeof(buffer), fp);printf("%s", buffer);}fclose(fp);return 0;
}

編譯并運行程序后,就會將我們剛才寫入文件的內容讀取出來,并打印在顯示器上:

6、另一個讀文件的例子

#include <stdio.h>
#include <string.h>int main() {FILE *fp = fopen("myfile", "r");if(!fp) {printf("fopen error!\n");return 1;}char buf[1024];const char *msg = "hello bit!\n";while(1) {ssize_t s = fread(buf, 1, strlen(msg), fp);if(s > 0) {buf[s] = '\0';printf("%s", buf);}if(feof(fp)) {break;}}fclose(fp);return 0;
}

代碼功能

  1. 打開名為"myfile"的文件用于讀取

  2. 如果文件打開失敗,打印錯誤信息并退出

  3. 每次讀取與字符串"hello bit!\n"長度相同的數據塊(11字節)

  4. 將讀取的內容打印到標準輸出

  5. 遇到文件結尾時停止讀取

  6. 關閉文件并退出

代碼結構分析

  1. 文件打開部分

    FILE *fp = fopen("myfile", "r");
    if(!fp) {printf("fopen error!\n");return 1;
    }
    • 嘗試以只讀模式打開"myfile"文件

    • 如果打開失敗(fp為NULL),打印錯誤信息并返回1

  2. 變量定義

    char buf[1024];
    const char *msg = "hello bit!\n";
    • buf是1024字節的緩沖區

    • msg是字符串常量"hello bit!\n",用于確定每次讀取的長度

  3. 讀取循環

    while(1) {ssize_t s = fread(buf, 1, strlen(msg), fp);if(s > 0) {buf[s] = '\0';printf("%s", buf);}if(feof(fp)) {break;}
    }
    • 無限循環讀取文件內容

    • 每次讀取strlen(msg)(11)個字節到buf

    • 如果讀取到數據(s>0),在末尾添加'\0'使其成為字符串并打印

    • 檢查文件結束標志,如果到達文件末尾則退出循環

  4. 清理部分

    fclose(fp);
    return 0;
    • 關閉文件

    • 程序正常退出

編譯并運行輸出的結果:

稍作修改,實現簡單cat命令:

#include <stdio.h>
#include <string.h>int main(int argc, char* argv[]) {if (argc != 2) {printf("Usage: %s <filename>\n", argv[0]);return 1;}FILE *fp = fopen(argv[1], "r");if(!fp) {printf("fopen error!\n");return 2;}char buf[1024];while(1) {int s = fread(buf, 1, sizeof(buf), fp);if(s > 0) {buf[s] = '\0';printf("%s", buf);}if(feof(fp)) {break;}}fclose(fp);return 0;
}

1. 代碼功能

  • 從命令行接收一個文件名,并嘗試打開該文件。

  • 逐塊讀取文件內容(每次最多?1024?字節),并打印到標準輸出(stdout)。

  • 檢測文件結束(EOF),并在讀取完成后關閉文件。

2. 代碼解析

(1) 參數檢查

if (argc != 2) {printf("Usage: %s <filename>\n", argv[0]);return 1;
}
  • argc?表示命令行參數的個數,argv[0]?是程序名,argv[1]?是傳入的文件名。

  • 如果用戶未提供文件名(argc != 2),打印用法提示并返回?1(表示錯誤)。

(2) 打開文件

FILE *fp = fopen(argv[1], "r");
if(!fp) {printf("fopen error!\n");return 2;
}
  • 嘗試以?只讀模式("r"?打開文件?argv[1]

  • 如果打開失敗(fp == NULL),打印錯誤信息并返回?2

(3) 讀取文件內容

char buf[1024];
while(1) {int s = fread(buf, 1, sizeof(buf), fp);if(s > 0) {buf[s] = '\0';  // 添加字符串結束符printf("%s", buf);}if(feof(fp)) {break;}
}
  • fread?讀取數據

    • buf:存儲數據的緩沖區。

    • 1:每個元素的大小(字節)。

    • sizeof(buf):每次最多讀取?1024?字節。

    • fp:文件指針。

    • 返回值?s:實際讀取的字節數(可能小于?1024)。

  • printf?打印數據

    • buf[s] = '\0':確保?buf?是一個合法的 C 字符串(printf?需要?\0?結尾)。

    • printf("%s", buf):打印讀取的內容。

  • feof(fp)?檢測文件結束

    • 如果?fread?返回?0?且?feof(fp)?為真,說明文件已經讀完,退出循環。

(4) 關閉文件

fclose(fp);
return 0;
  • 關閉文件,防止資源泄漏。

  • 返回?0?表示程序正常結束。

3. 關鍵點分析

(1)?fread?的返回值

  • s > 0:成功讀取數據,存入?buf?并打印。

  • s == 0

    • 如果?feof(fp)?為?true,說明文件已讀完,正常結束。

    • 如果?feof(fp)?為?false,可能是?讀取錯誤(但代碼未處理)。

(2)?buf[s] = '\0'?的作用

  • fread?不會自動添加?'\0',但?printf("%s", buf)?需要?'\0'?作為字符串結束符。

  • 如果文件是?二進制數據,可能會因為?'\0'?導致?printf?提前終止輸出。

(3) 循環終止條件

  • feof(fp)?為?true:文件讀完,正常退出。

  • 如果?fread?返回?0?但?feof(fp)?仍為?false

    • 可能是?讀取錯誤(如文件損壞)。

    • 當前代碼?不會檢測這種情況,可能導致?無限循環

編譯并運行輸出結果:


四、輸出信息到顯示器的常用方法

#include <stdio.h>
#include <string.h>int main() {const char *msg = "hello fwrite\n";fwrite(msg, strlen(msg), 1, stdout);printf("hello printf\n");fprintf(stdout, "hello fprintf\n");return 0;
}

1、代碼功能

  • 使用?fwrite?直接寫入二進制數據。

  • 使用?printf?格式化輸出字符串。

  • 使用?fprintf?向指定流(這里是?stdout)輸出格式化字符串。

2、代碼解析

(1)?fwrite?方式

const char *msg = "hello fwrite\n";
fwrite(msg, strlen(msg), 1, stdout);
  • fwrite?是?二進制寫入函數,適用于任何數據(包括字符串、二進制數據等)。

  • 參數解析

    • msg:要寫入的數據("hello fwrite\n")。

    • strlen(msg):寫入的?每個元素的大小(這里是字符串長度,不包括?'\0')。

    • 1:寫入的元素個數(這里是?1?個字符串)。

    • stdout:輸出流(標準輸出)。

  • 特點

    • 不會自動添加?'\0',因為它?不關心數據內容,只是按字節寫入。

    • 適合?二進制寫入(如文件 I/O),但也可以用于字符串。

(2)?printf?方式

printf("hello printf\n");
  • printf?是?格式化輸出函數,默認輸出到?stdout

  • 特點

    • 自動處理?'\0'?結尾,適合?文本輸出

    • 支持格式化字符串(如?%d,?%s?等)。

(3)?fprintf?方式

fprintf(stdout, "hello fprintf\n");
  • fprintf?是?指定流的格式化輸出,可以輸出到任意文件流(如?stdout、文件等)。

  • 參數解析

    • stdout:指定輸出流(這里仍然是標準輸出)。

    • "hello fprintf\n":要輸出的字符串。

  • 特點

    • 和?printf?類似,但可以指定輸出目標(如文件、標準錯誤?stderr?等)。

    • 適合需要?靈活控制輸出目標?的場景。

3、輸出結果

編譯并運行程序后,輸出如下:

  • fwrite?和?printf/fprintf?都能正確輸出字符串。

  • 但它們的?底層機制不同

    • fwrite?是?二進制寫入,不關心字符串格式。

    • printf?和?fprintf?是?格式化輸出,更適合文本。

4、關鍵區別

函數類型是否處理?'\0'適用場景示例
fwrite二進制寫入? 不處理文件 I/O、二進制數據fwrite(data, 1, size, fp);
printf格式化輸出? 自動處理標準輸出、格式化文本printf("num=%d", 123);
fprintf流格式化輸出? 自動處理任意流(文件、stdoutstderrfprintf(stderr, "Error: %s", errmsg);

5、使用場景建議

  1. 如果要寫入字符串到?stdout,優先用?printf?或?fprintf

    • 它們會自動處理?'\0',更安全。

    • 支持格式化(如?%d,?%f)。

  2. 如果要寫入二進制數據(如圖片、結構體),用?fwrite:它不會修改數據,適合原始字節流。

  3. 如果要輸出到文件或?stderr,用?fprintf:可以靈活指定輸出目標。

6. 擴展:puts?和?fputs

如果只是簡單輸出字符串,還可以用:

puts("hello puts");       // 自動加換行
fputs("hello fputs", stdout);  // 不加換行
  • puts?會自動在末尾加?'\n',而?fputs?不會。

7. 總結

  • fwrite:底層二進制寫入,適合非文本數據。

  • printf:標準格式化輸出,默認到?stdout

  • fprintf:可指定輸出流的格式化寫入(如文件、stderr)。

  • puts/fputs:更簡單的字符串輸出方式。

這段代碼展示了三種不同的輸出方式,實際使用時可以根據需求選擇最合適的函數。?


五、?什么是當前路徑?

????????當使用fopen以寫入模式打開文件時,若文件不存在,系統會在當前工作目錄自動創建該文件。這里的"當前路徑"具體指程序運行時的工作目錄。

????????例如上面的例子中,在當前工作目錄(~目錄)下運行可執行程序demo1時,程序創建的log.txt文件默認會生成在~目錄中:

????????我們可以理解為:"當前路徑"指的是可執行程序運行時所在的路徑。為了驗證這一點,我們可以進行以下測試:

  1. 首先刪除之前生成的log.txt文件
  2. 在當前工作目錄中,創建一個新目錄,將可執行程序demo1拷貝到這個新目錄中
  3. cd到這個新目錄中重新運行該程序,觀察log.txt生成在哪里

????????運行該可執行程序后,我們發現log.txt文件并未在~目錄下生成,而是出現在當前工作目錄newdir中!!!這與結論相符!!!

????????當程序運行成為進程后,我們可以通過獲取其PID來查看相關信息。該進程的詳細信息存儲在根目錄下的proc目錄中,可通過對應PID進行訪問。

? ? ? ? 為了可以查看相關信息,我們把demo1.c改為每寫入一句字符串就休眠5秒,不至于查看信息的時候看不到現象:

#include <stdio.h>
#include <unistd.h>int main()
{FILE* fp = fopen("log.txt", "w");if (fp == NULL){perror("fopen");return 1;}int count = 5;while (count){fputs("hello world\n", fp);sleep(5);count--;}fclose(fp);return 0;
}

命令解析:ps -axj | head -1 && ps -axj | grep demol | grep -v grep

  1. ps -axj | head -1

    • ps -axj:顯示所有用戶的進程(a),包括無控制終端的進程(x),并以作業格式(j)顯示

    • head -1:只保留第一行輸出(即列標題)

    • 這部分的作用是顯示進程列表的標題行

  2. ps -axj | grep demo1 | grep -v grep

    • ps -axj:同上,獲取所有進程的完整列表

    • grep demo1:過濾出包含"demo1"的行

    • grep -v grep:排除掉grep自身的進程(因為grep命令本身也會出現在進程列表中)

組合效果:

  • 先顯示進程列表的標題行

  • 然后顯示所有包含"demo1"的進程信息(不包括grep自身的進程)

其中:

  • cwd:指向當前進程運行目錄的符號鏈接
  • exe:指向啟動當前進程的可執行文件(含完整路徑)的符號鏈接

????????當打開文件時,實際上是進程在執行文件的操作。由于進程知道自身所在位置,即便文件不帶路徑信息,進程也能準確定位。因此,操作系統能夠明確新創建文件的存儲位置。

????????需要強調的是,這里所說的"當前路徑"并非指可執行程序的存儲位置,而是指程序運行成為進程時所在的工作目錄路徑。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89429.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89429.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89429.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【自用】JavaSE--集合框架(一)--Collection集合體系

概述之前學的ArrayList就是集合的一種&#xff0c;是一種容器&#xff0c;可以往里面存東西&#xff0c;大小可變Collection集合體系Collection的常用方法以后Collection體系的集合都可以用下圖的方法注意toArray方法的數組類型是Object&#xff0c;這樣就可以接收任意類型的數…

電腦視頻常用幾種接口

傳輸信號類型 DP&#xff08;DisplayPort&#xff09;主要用于傳輸數字視頻和音頻信號&#xff0c;支持高分辨率和高刷新率。HDMI&#xff08;High-Definition Multimedia Interface&#xff09;同樣傳輸數字音視頻信號&#xff0c;但更偏向消費電子領域&#xff0c;如電視、游…

CherryStudio+playwright-mcp-server實現AI自動化

目錄 1、CherryStudio安裝與配置 1.1什么是CherryStudio 1.2安裝 1.3配置 2、playwright-mcp-server的安裝與配置 3、執行測試與結果 1、CherryStudio安裝與配置 1.1什么是CherryStudio Cherry Studio 是一款集多模型對話、知識庫管理、AI 繪畫、翻譯等功能于一體的全能 …

深入了解 find_element 方法:Web 自動化定位元素的核心?

在 Web 自動化測試領域&#xff0c;元素定位是實現各類操作的基礎&#xff0c;而find_element方法正是 Selenium 等自動化工具中用于定位單個元素的核心方法。掌握它的使用技巧&#xff0c;能讓我們更精準、高效地操控網頁元素&#xff0c;為自動化測試腳本的編寫打下堅實基礎。…

從零開始的云計算生活——第三十三天,關山阻隔,ELK日志分析

目錄 一.故事背景 二、Elasticsearch 全面概述 1、核心定位 2、核心特性 a. 分布式架構 b. 高性能原理 c. 數據模型創新 3、核心技術組件 4、核心應用場景 a. 企業級搜索 b. 可觀測性 c. 安全分析&#xff08;SIEM&#xff09; 5、版本演進關鍵特性 6、核心優勢…

深入理解 Spring Boot Starter 的生成機制

在使用 Spring Boot 進行開發時&#xff0c;我們常常會引入諸如 spring-boot-starter-web、spring-boot-starter-data-jpa 等依賴&#xff0c;從而快速開啟相關功能模塊。但你是否思考過這些 Starter 是如何構建的&#xff1f;如果我們要開發自己的 Starter&#xff0c;又該如何…

阿里云-通義靈碼:隱私保護機制—為數據安全筑起銅墻鐵壁

免責聲明&#xff1a;此篇文章所有內容皆是本人實驗&#xff0c;并非廣告推廣&#xff0c;并非抄襲&#xff0c;該系列繼續~每日一句不要感嘆自己的平凡&#xff0c;即便是最暗的星星&#xff0c;相與無邊的黑暗已是耀眼。一.引言在這個數據如同空氣般滲透到生活每個角落的時代…

最小生成樹算法詳解

最小生成樹算法詳解一、最小生成樹基礎概念1.1 生成樹與最小生成樹1.2 核心性質1.3 應用場景二、Prim 算法&#xff1a;從頂點出發的“生長式”構建2.1 算法原理2.2 Java 代碼實現&#xff08;鄰接矩陣版&#xff09;2.3 復雜度分析三、Kruskal 算法&#xff1a;按邊權排序的“…

YOLO 目標檢測的改進方法

YOLO目標檢測的改進方法可以從模型架構、訓練策略、損失函數等多個方面入手&#xff0c;以下是一些常見的改進方法方向及參考文獻&#xff1a; 模型架構改進 骨干網絡替換&#xff1a;使用更輕量或更強大的網絡替換原始骨干網絡。輕量級網絡如MobileNetV3、ShuffleNetV2等適合…

C++ 程序 AddressSanitizer:DEADLYSIGNAL

GCC && G 操作系統&#xff1a;Ubuntu 22.04 現象&#xff1a;C程序編譯時開啟ASAN&#xff0c;運行時有幾率會出現大量AddressSanitizer:DEADLYSIGNAL 參考文章&#xff1a; https://stackoverflow.com/questions/77894856/possible-bug-in-gcc-sanitizers https://st…

【強化學習】實際部署

環境 Gymnasium 作為環境接口&#xff0c; PyBullet作為物理仿真平臺&#xff0c; Stable Baselines3 用于訓練算法。 測試框架搭建 以pybullet自帶的Cart-pole-v1為例 安裝依賴&#xff1a;確保安裝了 Gymnasium 和 SB3 ( pip install gymnasium stable-baselines3 ).初始化環…

集訓Demo4

創建數據庫創建項目基本和視頻中的一樣我給User添加了vip這個屬性&#xff0c;想實現兩個令牌通過訪問的案例&#xff0c;但遇到了問題一個令牌是密碼加用戶名的map數組這是它的獲取、驗證邏輯獲取驗證另一個令牌是Int vip這是自己寫的另一套密鑰和方法獲取但在驗證這里有問題頭…

深度優化:Java 慢查詢排查與性能調優實戰

文章目錄&#x1f680; 深度優化&#xff1a;Java 慢查詢排查與性能調優實戰&#x1f6a8;1. 事故全景&#xff1a;從告警到定位&#x1f575;??♂?1.1 事故時間線&#x1f4ca; 1.2 關鍵指標異常&#x1f6e0;? 1.3 排查工具鏈&#x1f50d; 2. 深度剖析&#xff1a;MySQL…

TF-IDF(Term Frequency - Inverse Document Frequency)

TF-IDF&#xff08;Term Frequency - Inverse Document Frequency&#xff09;是一種在信息檢索與文本挖掘中非常常用的關鍵詞提取方法&#xff0c;用于衡量一個詞在文檔集合中的重要性。它的核心思想是&#xff1a;如果一個詞在某個文檔中出現得頻繁&#xff0c;同時在其他文檔…

Chrome緊急更新,谷歌修復正遭活躍利用的關鍵零日漏洞

谷歌已針對桌面版Chrome發布重要穩定渠道更新&#xff08;版本138.0.7204.157/.158&#xff09;&#xff0c;修復了六個安全漏洞&#xff0c;其中包括一個已被實際利用的漏洞。該更新正在向Windows、Mac和Linux平臺推送&#xff0c;預計未來數日或數周內將通過自動更新完成部署…

Typecho插件開發:實現文章字數統計與閱讀時長計算功能

文章目錄 Typecho文章字數統計與閱讀時長計算功能實現指南 1. 功能背景與需求分析 2. 插件設計與實現 2.1 插件基礎結構 2.2 插件主邏輯實現 2.3 代碼解析與優化 3. 前端展示優化 3.1 CSS樣式增強 3.2 多語言支持 4. 高級功能擴展 4.1 數據庫表優化 4.2 定時批量處理歷史文章 5…

開源短鏈接工具 Sink 無需服務器 輕松部署到 Workers / Pages

本文首發于只抄博客,歡迎點擊原文鏈接了解更多內容。 前言 Sink 是一款開源免費的短鏈接生成工具,支持自定義短鏈接 Slug 以及設置到期時間,并且還可以借助 Cloudflare 的 Analytics Engine 功能分析短鏈接的統計數據。 最重要的是實現以上這些功能并不需要有自己的服務器,…

嵌入式數據結構之順序表總結

以下是為嵌入式面試準備的順序表全面優化指南&#xff0c;結合高頻考點、代碼規范與嵌入式專項優化技巧&#xff0c;助你系統掌握該知識點。 一、順序表基礎與嵌入式特點 ?本質? 用連續內存空間存儲線性表元素&#xff0c;通過下標實現O(1)隨機訪問 。 ?嵌入式優勢?&#x…

Pytorch下載Mnist手寫數據識別訓練數據集的代碼詳解

datasets.MNIST(root./data, trainFalse, downloadTrue, transformtransforms.ToTensor())1. datasets.MNIST這是torchvision.datasets模塊中的一個類&#xff0c;專門用于加載MNIST數據集。MNIST是一個著名的手寫數字識別數據集&#xff0c;包含60,000個訓練樣本和10,000個測試…

汽車免拆診斷案例 | 07款豐田Hilux啟動故障

故障現象一輛 2007 年的豐田Hilux 2.5L柴油手動擋&#xff0c;行駛里程為23萬公里。車主說車輛有很多故障&#xff0c;包括故障燈閃爍、發動機啟動后又熄火、短時間運行時發動機還會劇烈抖動異響&#xff0c;從排氣管冒出大量煙霧。故障診斷接車之后進行檢查&#xff0c;發現發…