⽂件操作

为什么使⽤⽂件?

如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件。

什么是⽂件?

磁盘(硬盘)上的⽂件是⽂件。但是在程序设计中,我们⼀般谈的⽂件有两种:程序⽂件、数据⽂件(从⽂件功能的⻆度来分类的)。

程序⽂件

程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows 环境后缀为.exe)。

数据⽂件

⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或者输出内容的⽂件。在以前所处理数据的输⼊输出都是以终端为对象的,即从终端的键盘输⼊数据,运⾏结果显⽰到显⽰器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使⽤,这⾥处理的就是磁盘上⽂件。

⽂件名

⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤。
⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀
例如:c:\code\test.txt
为了⽅便起⻅,⽂件标识常被称为⽂件名。

⼆进制⽂件和⽂本⽂件?

根据数据的组织形式,数据⽂件被称为⽂本⽂件或者⼆进制⽂件。数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存的⽂件中,就是⼆进制⽂件。 如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂ 本⽂件。⼀个数据在⽂件中是怎么存储的呢?字符⼀律以ASCII形式存储,数值型数据既可以⽤ASCII形式存储,也可以使⽤⼆进制形式存储。如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占⽤5个字节(每个字符⼀个字节),⽽⼆进制形式输出,则在磁盘上只占4个字节。

举例

int main() {
	int i = 10000;
	FILE* pf = fopen("test.txt", "wb");
	fwrite(&i, 4, 1, pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

在vs上打开二进制文件

⽂件的打开和关闭

流和标准流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出 操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。

标准流

那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢?那是因为C语⾔程序在启动的时候,默认打开了3个流:
• stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
• stdout - 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出 流中。
• stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯。 
这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。stdin、stdout、stderr三个流的类型是:FILE * ,通常称为⽂件指针。C语⾔中,就是通过  FILE* 的⽂件指针来维护流的各种操作的。

⽂件指针

缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系 统声明的,取名FILE.
例如,VS2013编译环境提供的  stdio.h 头⽂件中有以下的⽂件类型申明:

struct _iobuf {
char *_ptr; 
int   _cnt; 
char *_base; 
int   _flag; 
int   _file; 
int   _charbuf; 
int   _bufsiz; 
char *_tmpfname;
};

typedef struct _iobuf FILE;

不同的C编译器的FILE类型包含的内容不完全相同,但是⼤同⼩异。每当打开⼀个⽂件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信 息,使⽤者不必关⼼细节。
⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使⽤起来更加⽅便。下⾯我们可以创建⼀个FILE*的指针变量:

FILE* pf

定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个⽂件的⽂件信息区(是⼀个结构体变量)。通过该⽂件信息区中的信息就能够访问该⽂件。也就是说,通过⽂件指针变量能够间接找到与它关联的⽂件。

⽂件的打开和关闭

⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了 指针和⽂件的关系。ANSI C 规定使⽤fopen函数来打开⽂件,fclose 来关闭⽂件。

//打开文件
FILE * fopen(const char * filename,const char * mode);

//关闭文件
int fclose(FILE * stream);

mode表示文件的打开方式,下面是文件的打开模式

⽂件使⽤⽅式  含义如果指定⽂件不存在
“r”(只读)为了输⼊数据,打开⼀个已经存在的⽂本⽂件出错
“w”(只写)为了输出数据,打开⼀个⽂本⽂件建⽴⼀个新的⽂件
“a”(追加)向⽂本⽂件尾添加数据建⽴⼀个新的⽂件
“rb”(只读)为了输⼊数据,打开⼀个⼆进制⽂件                                     出错
“wb”(只写)为了输出数据,打开⼀个⼆进制⽂件建⽴⼀个新的⽂件
“ab”(追加)向⼀个⼆进制⽂件尾添加数据建⽴⼀个新的⽂件
“r+”(读写)为了读和写,打开⼀个⽂本⽂件出错
“w+”(读写)为了读和写,建议⼀个新的⽂件建⽴⼀个新的⽂件
“a+”(读写)打开⼀个⽂件,在⽂件尾进⾏读写建⽴⼀个新的⽂件
“rb+”(读写)为了读和写打开⼀个⼆进制⽂件出错
“wb+”(读写)为了读和写,新建⼀个新的⼆进制⽂件建⽴⼀个新的⽂件
“ab+”(读写)打开⼀个⼆进制⽂件,在⽂件尾进⾏读和写建⽴⼀个新的⽂件

注意:所谓的读是从文件向内存读取数据,写是从内存向文件写数据

实例代码:

int main() {
	FILE* pFile;
	pFile = fopen("myfile.txt", "w");
	if (pFile != NULL) {
		fput("fopen example", pFile);
		fclose(pFile);
	}
    return 0;
}

⽂件的顺序读写

顺序读写函数介绍

fgetc

举例

int main() {
	FILE* pf = fopen("file.txt", "r");
	if (pf == NULL) {
		fputs("fopen example", pf);
		return 1;
	}
	do { 
		int c = fgetc(pf);
		if (feof(pf)) {
			break;
		}	
		printf("%c", c);
	} while (1);
	fclose(pf);
	pf = NULL;
	return 0;
}

fputc

举例

int main() {
	FILE* pf = fopen("file.txt", "w+");
	int i = 0;
    if(pf == NULL) {
      perror("打开文件时发生错误");
      return(-1);
   }
	for (i = 33;i <= 100;i++) {
		fputc(i, pf);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

输出结果

fgets

举例

int main() {
	char arr[100];
	FILE * pf = fopen("file.txt", "r");
	if (pf == NULL) {
		perror("打开文件时发生错误");
		return(-1);
	}
	if (fgets(arr,100,pf)) {
		puts(arr);
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

输出结果

fputs

举例

int main() {
	FILE* pf = fopen("file.txt", "w");
	if (pf == NULL) {
		perror("打开文件时发生错误");
		return  1;
	}
	fputs("hello ", pf);
	fputs("word", pf);

	fclose(pf);
	pf = NULL;
	return 0;
}

输出结果

fscanf

int main()
{
	char str1[10], str2[10], str3[10];
	int year;
	FILE* fp;

	fp = fopen("file.txt", "w+");
	fputs("We are in 2014", fp);

	rewind(fp);
	fscanf(fp, "%s %s %s %d", str1, str2, str3, &year);

	printf("Read String1 |%s|\n", str1);
	printf("Read String2 |%s|\n", str2);
	printf("Read String3 |%s|\n", str3);
	printf("Read Integer |%d|\n", year);

	fclose(fp);

	return(0);
}

输出结果

fprintf

举例

#include <stdio.h>
#include <stdlib.h>

int main()
{
   FILE * fp;

   fp = fopen ("file.txt", "w+");
   fprintf(fp, "%s %s %s %d", "We", "are", "in", 2014);
   
   fclose(fp);
   
   return 0;
}

最终结果在文件file.txt写入了We are in 2014

fread(二进制输入)

举例

 
int main()
{
   FILE *fp;
   char c[] = "This is runoob";
   char buffer[20];
 
   /* 打开文件用于读写 */
   fp = fopen("file.txt", "w+");
 
   /* 写入数据到文件 */
   fwrite(c, strlen(c) + 1, 1, fp);
 
   /* 查找文件的开头 */
   fseek(fp, 0, SEEK_SET);
 
   /* 读取并显示数据 */
   fread(buffer, strlen(c)+1, 1, fp);
   printf("%s\n", buffer);
   fclose(fp);
   
   return 0;
}

fwrite(二进制输出)

举例

#include<stdio.h>
 
int main ()
{
   FILE *fp;
   char str[] = "This is runoob.com";
 
   fp = fopen( "file.txt" , "w" );
   fwrite(str, sizeof(str) , 1, fp );
 
   fclose(fp);
  
   return(0);
}

⽂件的随机读写

fseek

根据⽂件指针的位置和偏移量来定位⽂件指针(⽂件内容的光标)。

int fseek ( FILE * stream, long int offset, int origin );

举例

int main ()
{
   FILE *fp;

   fp = fopen("file.txt","w+");
   fputs("This is runoob.com", fp);
  
   fseek( fp, 7, SEEK_SET );
   fputs(" C Programming Langauge", fp);
   fclose(fp);
   
   return(0);
}

ftell

返回⽂件指针相对于起始位置的偏移量

long int ftell ( FILE * stream );

举例

int main ()
{
   FILE *fp;
   int len;

   fp = fopen("file.txt", "r");
   if( fp == NULL ) 
   {
      perror ("打开文件错误");
      return(-1);
   }
   fseek(fp, 0, SEEK_END);

   len = ftell(fp);
   fclose(fp);

   printf("file.txt 的总大小 = %d 字节\n", len);
   
   return(0);
}

rewind

让⽂件指针的位置回到⽂件的起始位置

void rewind ( FILE * stream );

举例

int main()
{
   char str[] = "This is runoob.com";
   FILE *fp;
   int ch;

   /* 首先让我们在文件中写入一些内容 */
   fp = fopen( "file.txt" , "w" );
   fwrite(str , 1 , sizeof(str) , fp );
   fclose(fp);

   fp = fopen( "file.txt" , "r" );
   while(1)
   {
      ch = fgetc(fp);
      if( feof(fp) )
      {
          break ;
      }
      printf("%c", ch);
   }
   rewind(fp);
   printf("\n");
   while(1)
   {
      ch = fgetc(fp);
      if( feof(fp) )
      {
          break ;
      }
      printf("%c", ch);
     
   }
   fclose(fp);

   return(0);
}

⽂件读取结束的判定

被错误使⽤的feof

牢记:在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。feof 的作⽤是:当⽂件读取结束的时候,判断是读取结束的原因是否是:遇到⽂件尾结束。

1. ⽂本⽂件读取是否结束,判断返回值是否为 EOF(   fgetc ),或者NULL(   fgets )例如:
• fgetc 判断是否为  EOF .
• fgets 判断返回值是否为NULL .                                                                                                      2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。                                         例如:
• fread判断返回值是否⼩于实际要读的个数。

实例

int main ()
{
   FILE *fp;
   int c;
  
   fp = fopen("file.txt","r");
   if(fp == NULL) 
   {
      perror("打开文件时发生错误");
      return(-1);
   }
   while(1)
   {
      c = fgetc(fp);
      if( feof(fp) )
      { 
          break ;
      }
      printf("%c", c);
   }
   fclose(fp);
   return 0;
}

⽂件缓冲区

ANSIC标准采⽤“缓冲⽂件系统”处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为 程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的⼤⼩根据C编译系统决定的。

C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂ 件。如果不做,可能导致读写⽂件的问题。

1. 代码规范:类名采⽤驼峰命名法(如 ExamGenerator ),变量名⼩写加下划线(如 student_id )。 2. 账号管理:每个题⽬有两类⽤户,除了题⽬规定的功能外,为⽤户设计账号登陆退出功能。 3. 错误处理:操作包含 try-catch 块,捕获并提示 std::ios::failure 异常。 4. 测试⽤例:报告中为每个功能提供2个功能以上的测试⽤例。 题⽬1 “在线学习平台智能题库系统设计”  1. 问题描述  设计⼀个供教师和学⽣使⽤的智能题库系统,⽀持题⽬录⼊、智能组卷、学习数据分析功能。 2. 功能要求  1. 题库管理(教师端) 题⽬录⼊:教师通过命令⾏输⼊题⽬信息(题⼲、选项、答案、知识点标签、难度系数1-5),保存到 questions.txt ,格 式为: 题⽬修改:输⼊题⽬ID,⽀持修改题⼲或答案,修改后同步更新。 2. 智能组卷(教师端) 规则输⼊:教师输⼊知识点(如“继承”)、题⽬数量(如10题)、难度范围(如2-4),系统从题库中随机抽取符合条的题⽬ ⽣成试卷。 ⼿动调整:允许教师替换试卷中的题⽬,替换后⽣成新试卷 exam_001.txt 。 3. 答题与评分(学⽣端) 答题:学⽣输⼊答案(如“A,B,C”),系统对⽐标准答案并计算得分。 成绩记录:将学⽣ID、得分、答题时间写⼊ scores.csv ,格式为: 4. 学习报告(学⽣端) 报告⽣成:每周⼀⾃动⽣成报告 report_20231001.txt ,内容包括: 3. 问题的解决⽅案  1. 类设计 Question 类: 属性: id , content , options , answer , tag , difficulty ⽅法: saveToFile() , loadFromFile() ExamGenerator 类: ⽅法: randomSelect(vector<Question>&, int count) , exportExam(string filename) Student 类: 属性: id , password [ID] 题⼲:C++中继承的三种类型是? 选项:A.公有 B.私有 C.保护 D.静态 答案:A,B,C 知识点:继承 难度:3 20231001,85,2023-10-01 14:30
04-29
源码来自:https://pan.quark.cn/s/a3a3fbe70177 AppBrowser(Application属性查看器,不需要越狱! ! ! ) 不需要越狱,调用私有方法 --- 获取完整的已安装应用列表、打开和删除应用操作、应用运行时相关信息的查看。 支持iOS10.X 注意 目前AppBrowser不支持iOS11应用查看, 由于iOS11目前还处在Beta版, 系统API还没有稳定下来。 等到Private Header更新了iOS11版本,我也会进行更新。 功能 [x] 已安装的应用列表 [x] 应用的详情界面 (打开应用,删除应用,应用的相关信息展示) [x] 应用运行时信息展示(LSApplicationProxy) [ ] 定制喜欢的字段,展示在应用详情界面 介绍 所有已安装应用列表(应用icon+应用名) 为了提供思路,这里只用伪代码,具体的私有代码调用请查看: 获取应用实例: 获取应用名和应用的icon: 应用列表界面展示: 应用列表 应用运行时详情 打开应用: 卸载应用: 获取info.plist文: 应用运行时详情界面展示: 应用运行时详情 右上角,从左往右第一个按钮用来打开应用;第二个按钮用来卸载这个应用 INFO按钮用来解析并显示出对应的LSApplicationProxy类 树形展示LSApplicationProxy类 通过算法,将LSApplicationProxy类,转换成了字典。 转换规则是:属性名为key,属性值为value,如果value是一个可解析的类(除了NSString,NSNumber...等等)或者是个数组或字典,则继续递归解析。 并且会找到superClass的属性并解析,superClass如...
<think>好的,用户想了解文路径的相关概念、使用方法、常见问题及解决方案。我需要先理清文路径的基本概念,然后分绝对路径和相对路径来详细说明。记得结合用户提供的引用内容中的相关信息,比如引用[1]提到了相对路径和绝对路径的常见问题,引用[4]讨论了动态导入中的路径问题,这些都需要整合进来。 首先,文路径的基本概念。绝对路径是从根目录开始的完整路径,而相对路径是相对于当前工作目录的路径。用户可能需要知道两者的区别和使用场景。然后,使用方法部分,需要给出具体的例子,比如在Python中如何表示路径,或者在配置文中如何设置路径。 接下来是常见问题,比如路径解析错误、相对路径在打包后失效、绝对路径的移植性问题,以及动态导入模块时的路径问题。这些问题在用户提供的引用中都有涉及,比如引用[4]提到PyInstaller打包时动态导入模块的路径问题,需要详细说明。 解决方案部分,需要针对每个问题给出具体的解决办法。例如,使用正确的路径分隔符,优先使用相对路径并明确基准目录,或者在打包工具中配置额外资源。同时,引用[2]中提到Vue项目中使用相对路径配置接口路径,这也是一个解决方案的例子。 还要注意用户提到的系统级指令,比如数学表达式用$...$格式,独立公式用$$...$$,但这个问题可能不需要数学公式,所以可能用不到。但需要确保回答结构清晰,分点列出,符合用户的要求。 最后生成相关问题,要围绕文路径的应用场景、不同系统中的路径处理、动态导入路径问题以及路径配置错误处理等方面提问。这样可以帮助用户进一步深入理解。 现在需要检查是否有遗漏的信息,比如引用[3]提到的MySQL的问题可能与路径关系不大,但可能涉及数据文路径的配置,但用户的问题主要关注文路径,所以可能不需要涉及。重点还是放在引用[1]、[2]、[4]的内容上。 总结,回答的结构应该是:概念、使用方法、常见问题及解决方案、相关问题。每个部分都要简明扼要,结合实例和引用中的内容,确保用户能够清晰理解并解决实际问题。</think>### 文路径详解 #### 一、文路径基本概念 文路径是操作系统中用于定位文或目录的字符串,分为**绝对路径**和**相对路径**: - **绝对路径**:从根目录开始的完整路径,例如:`C:/project/src/main.py`(Windows)或 `/usr/local/nginx.conf`(Linux/macOS) - **相对路径**:基于当前工作目录的路径,例如:`./config/settings.json`(当前目录下的文)或 `../data/input.csv`(上级目录中的文) #### 二、使用方法 1. **路径分隔符** - Windows使用反斜杠`\`,但编程中建议统一用正斜杠`/`以避免转义问题,例如:`"src/images/logo.png"` - Linux/macOS默认使用正斜杠`/` 2. **编程中的路径处理** ```python # Python示例:路径拼接 import os base_dir = "project" sub_path = os.path.join(base_dir, "data", "output.txt") # 自动处理系统差异 ``` 3. **配置文中的路径设置** - 前端项目(如Vue)中接口路径配置可使用`./api/`表示当前目录[^2] - CMake项目中通过`include_directories(${PROJECT_SOURCE_DIR}/include)`设置头文路径[^1] #### 三、常见问题与解决方案 | 问题类型 | 现象示例 | 解决方案 | |---------------------------|-----------------------------------|--------------------------------------------------------------------------| | 路径解析错误 | 打包后提示"文不存在" | 使用`os.path.dirname(__file__)`获取脚本所在目录作为基准路径 | | 相对路径基准不明确 | 执行位置改变导致路径失效 | 明确声明基准目录(如`BASE_DIR = Path(__file__).parent.parent`) | | 绝对路径移植性差 | 更换环境后路径失效 | 使用环境变量或配置文动态构建路径(如`${HOME}/.config/app_settings`) | | 动态导入模块路径问题[^4] | PyInstaller打包后模块加载失败 | 通过`--hidden-import`手动指定模块,或使用`sys._MEIPASS`处理冻结环境路径 | #### 四、进阶实践技巧 1. **路径规范化** ```python # 消除路径中的冗余部分 from pathlib import Path print(Path("src/../main.py").resolve()) # 输出绝对路径并解析`..` ``` 2. **跨平台兼容性** - 使用`pathlib`库代替字符串操作 - 处理特殊字符(如空格需转义为`\ `或加引号`"Program Files"`) 3. **调试建议** - 打印当前工作目录:`print(os.getcwd())` - 检查路径是否存在:`Path("data").exists()`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值