万字详解 C 语言文件操作

news2024/9/29 11:28:30

目录

一、什么是文件?

1.1 - 文件和流的基本概念

1.2 - 文件的分类

1.3 - 文件名

二、缓冲文件系统和非缓冲文件系统

三、文件指针类型

四、文件的打开和关闭

4.1 - fopen

4.2 - fclose

五、文件的顺序读写

5.1 - 字符输出函数 fputc

5.2 - 字符输入函数 fgetc

5.3 -  文本行输出函数 fputs

5.4 - 文本行输入函数 fgets

5.5 - 格式化输出函数 fprintf

5.6 - 格式化输入函数 fscanf

5.7 - 二进制输出函数 fwrite

5.8 - 二进制输入函数 fread

5.9 - 总结

5.10 - 对比一组函数

六、文件的随机读写

6.1 - fseek

6.2 - ftell

6.3 - rewind

七、文件读取结束的判定

7.1 - feof

7.2 - ferror

7.3 - 总结



一、什么是文件?

1.1 - 文件和流的基本概念

文件(File)流(stream)是既有区别又有联系的两个概念。

文件是一些具有永久存储及特定顺序的字节组成的一个有序的、具有名称的集合

流提供了一种向后备存储写入字节和从后备存储读取字节的方式,后备存储可以为多种存储媒介之一。正如除磁盘之外还存在多种后备存储一样,除文件流之外也存在多种流,例如,还存在网络流、内存流和磁带流等

1.2 - 文件的分类

从不同的角度可对文件作不同的分类

  • 从文件的功能角度来分类,文件可分为程序文件和数据文件

    1. 程序文件包括源程序文件,目标文件(windows 环境后缀为 .obj),可执行文件(windows 环境后缀为 .exe)。

    2. 文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

  • 根据数据的组织形式,文件可分为文本文件和二进制文件

    1. 二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放,即存放的是数据的原形式。

    2. 文本文件是把数据的终端形式的二进制数据输出到磁盘上存放,即存放的是数据的终端形式。

    计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有 ASCII 编码,UNICODE 编码等;二进制文件则是基于值编码的文件

    记事本支持文本文件而不支持二进制文件,所以用记事本打开文件文件则一切正常,如果打开的是二进制文件就会出现乱码。但也有不乱码的地方,那些地方都是字符编码的,因为字符数据本身在内存中就经过了编码,所以无论是二进制还是文本形式都是一样的,而对于 int、double 等类型所对应的值则都是乱码的

1.3 - 文件名

一个文件需要有唯一的文件标识(即文件名),以便用户识别和引用

文件名包含 3 个部分

  1. 文件路径

    • 绝对路径,也称为完整路径,是指向文件系统中某个固定位置的路径,不会因当前的工作目录而产生变化。为了做到这点,它必须包含根目录

      在计算机的文件系统中,根目录指文件系统的最上一级目录,它是相对子目录来说的,它如同一棵大树的"根"一般,所有的树杈都以它为起点,故被命名为根目录

      以微软公司开发的 Windows 操作系统为例:打开这台电脑(我的电脑、计算机),双击 C 盘就进入 C 盘的根目录,双击 D 盘就进入 D 盘的根目录

      Unix 完全抽象了树层次结构的本质,在 Unix 和类 Unix 系统中,根目录用 / 符号表示。虽然根目录通常称为 /,但目录条目本身没有名称,它的名称是初始目录分隔符(/)之前的"空"部分。所有文件系统条目(包括已挂载的文件系统)都是此根的"分支"

    • 相对路径则是以指定的工作目录作为基点,避开提供完整的绝对路径。文件名称就可以被视为以指定工作目录为基点的一个相对路径(虽然一般不将其称之为路径)。

      路径中的 "./" 代表目前所在的目录,"../" 代表上一级所在的目录,"../../" 则代表上上级所在的目录

  2. 文件名主干

  3. 文件后缀

    文件后缀名也叫文件扩展名,后缀名可以用来帮助用户了解文件是应该使用哪种软件打开文件


二、缓冲文件系统和非缓冲文件系统

C 语言所使用的磁盘文件系统有两大类:一类称为缓冲文件系统,又称为标准文件系统;另一类称为非缓冲文件系统

  1. 缓冲文件系统的特点

    系统自动地在内存区为每一个正在使用的文件开辟一个缓冲区,从磁盘向内存读入数据时,则一次从磁盘文件将一些数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送给接受变量;向磁盘文件输出数据时,先将数据送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。

    用缓冲区可以一次读入一批数据,或输出一批数据,而不是执行一次输入或输出函数就去访问一次磁盘,这样做的目的是减少对磁盘的实际读写次数,因为每一次读写都要移动磁头并寻找磁道扇区。缓冲区的大小由各个具体的 C 版本确定,一般为 512 byte,即 0.5 kb。

  2. 非缓冲文件系统的特点

    非缓冲文件系统不由系统自动设置缓冲区,而由用户自己根据需要设置。在传统的 Unix 系统下,用缓冲文件系统来处理文本文件,用非缓冲系统处理二进制文件。

    1983 年 ANSI C 标准决定不采用非缓冲文件系统,而只采用缓冲文件系统。即用缓冲文件系统处理文本文件,也用它来处理二进制文件,也就是将缓冲文件系统扩充为可以处理二进制文件

// VS 2019 WIN 10 环境测试
#include <stdio.h>
#include <windows.h>

int main()
{
	FILE* fp = fopen("test.txt", "w");
	fputs("hello world!", fp);
	printf("睡眠 10 秒 - 此时打开 test.txt 文件,会发现文件中没有内容\n");
	Sleep(10000);
	fflush(fp);// 刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
    // 注意:fflush 在高版本的 VS 上不能使用了
    printf("刷新缓冲区\n");
	printf("再睡眠 10 秒 - 此时再次打开 test.txt 文件,文件中就有内容了\n");
	Sleep(10000);
	fclose(fp);  // 注:fclose 在关闭文件的时候,也会刷新缓冲区
	fp = NULL;
	return 0;
}

文件操作相关的函数会在后面进行详解,我们只需要知道,根据这个程序,可以得出一个结论:因为有缓冲区的存在,在进行文件操作时,需要刷新缓冲区或者在文件操作结束时关闭文件,否则可能导致文件读写的问题


三、文件指针类型

缓冲文件系统中,关键的概念是"文件指针类型",简称"文件指针"

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字、文件状态以及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名为 FILE

例如,VS 2013 编译环境提供的 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 *fp;


四、文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件

ANSIC 规定使用 fopen 函数来打开文件,fclose 函数来关闭文件

4.1 - fopen

FILE* fopen(const char* filename, const char* mode);

参数

  • filename:要打开的文件的文件名。

  • mode:打开文件的方式。

    文件打开方式含义
    "r"read:打开文件进行输入操作(input operations),该文件必须存在
    "w"write:为输出操作(output operations)创建一个空文件,如果已存在同名文件,则会丢弃其内容,并将该文件视为新的空文件
    "a"append:打开文件在文件末尾进行输出操作(output operations),输出操作始终将数据写入(write)文件末尾,对其进行扩展。重新定位操作(repositioning operations)(fseekfsetposrewind)将被忽略。如果文件不存在,则创建一个新文件
    "r+"read/ update:打开文件进行输入输出操作,该文件必须存在
    "w+"write/ update:为输入输出操作创建一个空文件,如果已存在同名文件,则会丢弃其内容,并将该文件视为新的空文件
    "a+"append/ update:打开一个文件进行输入输出操作,所有输出操作都在文件末尾写入数据。重新定位操作(fseekfsetposrewind)会影响下一个输入操作,但输出操作会将位置移回文件末尾。如果文件不存在,则创建该文件。

    使用上面的打开方式,文件将作为文本文件打开

    为了将文件作为二进制文件打开,mode 中必须包含 b 字符。这个额外的 b 字符要么追加到末尾,从而形成复合的 mode:"rb"、"wb"、"ab"、"r+b"、"w+b"、"a+b",要么插入到字母和 + 号之间形成混合的 mode:"rb+"、"wb+"、"ab+"

返回值

如果文件打开成功,fopen 函数将返回一个 FILE 类型的指针,如果打开失败,则返回一个 NULL 指针,因此需要对 fopen 函数的返回值做检查

4.2 - fclose

int fclose(FILE* stream);

如果流(stream)成功关闭,则返回 0,失败则返回 EOF(本质上是 -1)

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("./test.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	fclose(fp);
	fp = NULL;
	return 0;
}

如果当前目录下并不存在 test.txt 文件,文件打开失败,终端上将会显示 "fopen: No such file or directory"


五、文件的顺序读写

5.1 - 字符输出函数 fputc

int fputc(int character, FILE* stream);

函数说明:将字符写入流中(Write character to stream)。

Writes a character to the stream and advances the position indicator.

返回值:写入成功,返回写入字符的 ASCII 值;写入失败,则返回 EOF 并设置错误指示器 error indicator(ferror

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("test_for_char.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	for (int ch = 'a'; ch <= 'z'; ch++)
	{
		fputc(ch, fp);  // 将小写字母 a ~ z 输出到文件当中
	}
	fclose(fp);
	fp = NULL;
	return 0;
}

5.2 - 字符输入函数 fgetc

int fgetc(FILE* stream);

函数说明:从流中读取字符(Get character from stream)。

Returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced to the next character.

返回值:读取成功,返回读取字符的 ASCII 值;如果遇到文件末尾,则返回 EOF 并设置文件末尾指示器 end-of-file indicator(feof;读取失败,则返回 EOF 并设置错误指示器。

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("test_for_char.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	int ch = 0;
	int cnt = 0;
	do
	{
		ch = fgetc(fp);
		if (ch >= 'a' && ch <= 'z')
		{
			cnt++;
		}
	} while (ch != EOF);
	printf("The file contains %d lowercase(a ~ z).\n", cnt);  // 26
	fclose(fp);
	fp = NULL;
	return 0;
}

5.3 -  文本行输出函数 fputs

int fputs(const char* str, FILE* stream);

函数说明:将字符串写入流中(Writes string to stream)。

The function begins copying from the address specified(str)until it reaches the terminating null character('\0'). This terminating null-character is not copied to the stream.

返回值:写入成功,返回一个非负数;写入失败,则返回 EOF 并设置错误指示器。

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("test_for_str.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	fputs("你好,世界!\n", fp);
	fputs("Hello World!\n", fp);
	fclose(fp);
	fp = NULL;
	return 0;
}

5.4 - 文本行输入函数 fgets

char* fgets(char* str, int num, FILE* stream);

函数说明:从流中读取字符串(Get string from stream)。

  • 从流中读取字符并将其存储到 str 指向内存空间中,直到读取了 num - 1 个字符或者遇到换行或者达到文件末尾。

  • 换行符('\n')会使 fgets 函数停止读取字符,但它被视为有效字符并存储到 str 指向的内存空间中。

  • str 指向的内存空间最后会自动添加一个字符串结束符 '\0'。

返回值:读取成功,返回字符串首字符的地址,即 str如果在尝试读取字符时遇到了文件末尾,则设置文件末尾指示器;如果在读取任何字符之间发生这种情况,则返回 NULL,str 的内容保持不变);读取失败,则返回 NULL 并设置错误指示器(str 指向的内容可能已更改)。

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("test_for_str.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	char buf[20] = { 0 };
	printf("%s", fgets(buf, 20, fp));
	printf("%s", fgets(buf, 20, fp));
	fclose(fp);
	fp = NULL;
	return 0;
}

5.5 - 格式化输出函数 fprintf

int fprintf(FILE* stream, const char* format, ...);

函数说明:将格式化数据写入流中(Write formatted data to stream)。fprintf 函数和 printf 函数的功能相同,只是后者是将数据写到屏幕上。

返回值:写入成功,返回写入的字符总数;写入失败,则返回一个负数并设置错误指示器。

例如

#include <stdio.h>

struct Stu
{
	char name[20];
	int age;
};

int main()
{
	FILE* fp = fopen("test_for_format.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	struct Stu s = { "zhangsan", 18 };
	fprintf(fp, "%s %d\n", s.name, s.age);
	fclose(fp);
	fp = NULL;
	return 0;
}

5.6 - 格式化输入函数 fscanf

int fscanf(FILE* stream, const char* format, ...);

函数说明:从流中读取格式化数据(Read formatted data from stream)。

返回值

  • On success, the function returns the number of items of the argument list successfully filled. This count can match the expected number of items or be less (even zero) due to a matching failure, a reading error, or the reach of the end-of-file.

    If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.

例如

int main()
{
	FILE* fp = fopen("test_for_format.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	struct Stu s = { 0 };
	fscanf(fp, "%s %d", s.name, &s.age);
	fprintf(stdout, "%s %d", s.name, s.age);
	fclose(fp);
	fp = NULL;
	return 0;
}

5.7 - 二进制输出函数 fwrite

size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream);

函数说明:将 count 个元素的数组(每个元素的大小为 size,单位是字节)从 ptr 指向的内存块中写入到流中。

返回值:返回成功写入的元素总数;如果该数字和 count 不同,则表明出现写入错误,在这种情况下,设置错误指示器;如果 sizecount 为 0,函数则返回 0,错误指示器不变。

例如

#include <stdio.h>

struct Stu
{
	char name[20];
	int age;
};

int main()
{
	FILE* fp = fopen("test_for_binary.txt", "wb");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	struct Stu s = { "zhangsan", 18 };
	fwrite(&s, sizeof(struct Stu), 1, fp);
	fclose(fp);
	fp = NULL;
	return 0;
}

5.8 - 二进制输入函数 fread

size_t fread(void* ptr, size_t size, size_t count, FILE* stream);

函数说明:从流中读取 count 个元素的数组(每个元素的大小是 size,单位是字节),并将它们存储到 ptr 指向的内存块中。

返回值:返回成功读取的元素总数;如果该数字和 count 不同,则表明出现读取错误或遇到文件末尾,在这两种情况下,会设置正确的指示器,可以分别用 ferrorfeof 进行检查;如果 sizecount 为 0,函数则返回 0,并且流的状态和 ptr 指向的内容保持不变。

例如

#include <stdio.h>

struct Stu
{
	char name[20];
	int age;
};

int main()
{
	FILE* fp = fopen("test_for_binary.txt", "rb");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	struct Stu s = { 0 };
	fread(&s, sizeof(struct Stu), 1, fp);
	printf("%s %d\n", s.name, s.age);  // zhangsan 18
	fclose(fp);
	fp = NULL;
	return 0;
}

5.9 - 总结

功能函数名适用于
字符输出函数fputc所有输出流
字符输入函数fgetc所有输入流
文本行输出函数fputs所有输出流
文本行输入函数fgets所有输入流
格式化输出函数fprintf所有输出流
格式化输入函数fscanf所有输入流
二进制输出函数fwrite文件
二进制输入函数fread文件

5.10 - 对比一组函数

printf/ fprintf/ sprintf

scanf/ fscanf/ sscanf

sprintf:

int sprintf(char* str, const char* format, ...);

函数说明:将格式化数据写入到字符串中(Write formatted data to string)

sscanf: 

int sscanf(const char* s, const char* format, ...);

函数说明:从字符串中读取格式化数据(Read formatted data from string)

例如: 

#include <stdio.h>

struct Stu
{
	char name[20];
	int age;
};

int main()
{
	struct Stu s1 = { "zhangsan", 18 };
	char buf[20] = { 0 };
	sprintf(buf, "%s %d", s1.name, s1.age);  // 将格式化数据写入到字符串中
	printf("%s\n", buf);  // zhangsan 18

	struct Stu s2 = { 0 };
	sscanf(buf, "%s %d", s2.name, &s2.age);  // 从字符串中读取格式化数据
	printf("%s %d\n", s2.name, s2.age);  // zhangsan 18
	return 0;
}


六、文件的随机读写

6.1 - fseek

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

函数说明:根据 originoffset 移动文件指针。

参数

  • stream:Pointer to a FILE object that identifies the stream.

  • offset:偏移量。

  • origin:用作 offset 参考的位置,它可以是以下值:

    ConstantReference position
    SEEK_SETBeginning of file
    SEEK_CURCurrent position of the file pointer
    SEEK_ENDEnd of file *

返回值:成功返回 0,否则返回一个非零数。

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("test_for_fseek.txt", "wb");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	fputs("this is an apple.", fp);
	fseek(fp, 9, SEEK_SET);
	fputs(" sam", fp);
	fclose(fp);
	fp = NULL;
	return 0;
}

成功执行此代码后,test_for_fseek.txt 文件中包含:This is a sample.

6.2 - ftell

long int ftell(FILE* stream);

函数说明:返回文件指针相对于起始位置的偏移量。

返回值:成功返回位移量,否则返回 -1。

例如

#include <stdio.h>

int main()
{
    FILE* fp = fopen("test_for_ftell.txt", "rb");
    if (NULL == fp)
    {
        perror("fopen");
        return 1;
    }
    fseek(fp, 0, SEEK_END);   // non-portable
    long size = ftell(fp);
    fclose(fp);
    fp = NULL;
    printf("Size of test_for_ftell.txt: %ld bytes.\n", size);
    return 0;
}

该程序打印出 test_for_ftell.txt 文件的大小(单位是字节)

6.3 - rewind

void rewind(FILE* stream);

函数说明:让文件指针回到文件的起始位置。

返回值:无。

例如

#include <stdio.h>

int main()
{
	FILE* fp = fopen("test_for_rewind.txt", "w+");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	for (int n = 'A'; n <= 'Z'; n++)
	{
		fputc(n, fp);
	}
	rewind(fp);
	char buf[27] = { 0 };
	fread(buf, 1, 26, fp);
	puts(buf);  // ABCDEFGHIJKLMNOPQRSTUVWXYZ
	fclose(fp);
	fp = NULL;
	return 0;
}


七、文件读取结束的判定

7.1 - feof

int feof(FILE* stream);

函数说明:检查文件末尾指示器(Check end-of-file indicator)。

返回值:如果设置了与流关联的文件末尾指示器,则返回非零值,否则返回零。

7.2 - ferror

int ferror(FILE* stream);

函数说明:检查错误指示器(Check error indicator)。

返回值:如果设置了与流关联的错误指示器,则返回非零值,否则返回零。

7.3 - 总结

牢记:在文件读取过程中,不能用 feof 函数的返回值直接判断文件是否读取结束,而是应用于当文件读取结束时,判断是因为读取失败结束,还是因为遇到文件末尾结束

  1. 文本文件读取是否结束,判断返回值是否为 EOF(fgetc),或者 NULL(fgets)。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	FILE* fp = fopen("test_for_char.txt", "r");
    	if (NULL == fp)
    	{
    		perror("File Opening failed!");
    		return EXIT_FAILURE;
    	}
    	int ch = 0;  // 注意:int,而非 char,因为要处理 EOF
    	while ((ch = fgetc(fp)) != EOF)
    	{
    		putchar(ch);
    	}
    	putchar('\n');
    	if (ferror(fp))
    	{
    		puts("I/O error when reading");
    	}
    	else if (feof(fp))
    	{
    		puts("End of file reached successfully");
    	}
    	fclose(fp);
    	fp = NULL;
    	return 0;
    }
  2. 二进制文件读取是否结束,判断返回值是否小于实际要读取的个数。

     
    #include <stdio.h>
    
    int main(void)
    {
    	double a[5] = { 1.0, 2.0, 3.0, 4.0, 5.0 };
    	FILE* fp = fopen("test.bin", "wb"); 
    	fwrite(a, sizeof(double), 5, fp);
    	fclose(fp);
    
    	double b[5];
    	fp = fopen("test.bin", "rb");
    	size_t ret_code = fread(b, sizeof(double), 5, fp);
    	if (ret_code == 5) 
    	{
    		puts("Array read successfully, contents: ");
    		for (int n = 0; n < 5; ++n)
    			printf("%f ", b[n]);
    		putchar('\n');
    	}
    	else 
    	{
    		if (feof(fp))
    			printf("Error reading test.bin: unexpected end of file\n");
    		else if (ferror(fp))
    			perror("Error reading test.bin");
    	}
    	fclose(fp);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/186327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Kubernetes 企业项目实战】06、基于 Jenkins+K8s 构建 DevOps 自动化运维管理平台(上)

目录 一、k8s 助力 DevOps 在企业落地实践 1.1 传统方式部署项目为什么发布慢&#xff0c;效率低&#xff1f; 1.2 上线一个功能&#xff0c;有多少时间被浪费了&#xff1f; 1.3 如何解决发布慢&#xff0c;效率低的问题呢&#xff1f; 1.4 什么是 DevOps&#xff1f; …

【JavaScript】原型链

文章目录构造函数原型对象访问机制内置构造函数一切皆对象原型链构造函数 - 本质还是一个函数- 和 new 关键字连用- 特点1. 自动创建一个对象2. 自动返回一个对象3. 让函数的this指向这个对象 书写构造函数的时候1. 属性写在函数内2. 方法写在原型上构造函数的不合理 把方法写在…

Android studio 护眼模式配置、字体大小设置、内存大小设置等各类疑难杂症

Android studio 4.1 1、左边目录栏颜色配置&#xff1a; 2、代码编辑区域背景色设置 3、控制台背景色设置 4、菜单栏、工具栏、左边栏字体大小设置 5、编码区字体大小设置 6、修改内存大小、显示内存 例如&#xff1a;修改android-studio/bin/studio.vmoptions studio64.vmop…

NANK南卡护眼台灯Pro评测,护眼台灯天花板般存在!

现代大环境下&#xff0c;生活节奏和压力的不断加快加重&#xff0c;如今的手机、电脑屏幕以及长时间的工作学习都会出现用眼过度的问题&#xff0c;久而久之&#xff0c;各种眼睛刺痛、干涩、肿胀等近视问题接踵而至。为了保障自己的健康&#xff0c;近些年&#xff0c;人们纷…

回归预测 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入单输出

回归预测 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入单输出 目录回归预测 | MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入单输出预测效果基本介绍模型描述程序设计参考文献预测效果 基本介绍 MATLAB实现SSA-CNN麻雀算法优化卷积神经网络多输入单输出。 1 .data为…

基础课程11:调试工具

目标 有时事情不会按照预期进行&#xff0c;从总线(如果有的话)检索到的错误消息不能提供足够的信息。幸运的是&#xff0c;GStreamer附带了大量调试信息&#xff0c;这些信息通常会提示问题可能是什么。本教程展示了: 如何从GStreamer获取更多调试信息。 如何将自己的调试信…

电力电子器件简介

文章目录1、二极管2、BJT3、晶闸管&#xff08;SCR&#xff09;4、TRIAC5、GTO&#xff08;全控器件&#xff09;6、功率MOSFET&#xff08;开关速度快、电压驱动更容易&#xff09;7、IGBT8、总结![在这里插入图片描述](https://img-blog.csdnimg.cn/1d309b3d449040788c6437f8…

【胖虎的逆向之路】04——脱壳(一代壳)原理脱壳相关概念详解

【胖虎的逆向之路】04——脱壳&#xff08;一代壳&#xff09;原理&脱壳相关概念详解 【胖虎的逆向之路】01——动态加载和类加载机制详解 【胖虎的逆向之路】02——Android整体加壳原理详解&实现 【胖虎的逆向之路】03——Android一代壳脱壳办法&实操 文章目录【…

高速路如何避免ETC车辆漏计问题,ETC通道出入车辆校准看板

人群密集场所事故预防措施和应急管理方案的制定&#xff0c;对每一个交通枢纽和大型社会活动场所都显得尤为重要。对于交通管理部门来说&#xff0c;获取准确、可靠的交通数据已经变得越来越重要。 所以呢&#xff0c;ETC出入车辆校准看板是必要的。ETC出入车辆校准看板&#x…

如何使用路由策略解决 ISIS与OSPF双点双向产生的次优路径、环路隐患?

3.1.0 如何使用路由策略解决 ISIS与OSPF双点双向产生的次优路径、环路隐患 一、双点双向中的次优路径解决方法 双点双向中由于默认路由优先级造成次优路径的产生&#xff0c;而解决的方法就是修改路由优先级。 双点双向错误的解决方法 关于修改路由优先级&#xff0c;需要注…

2022 医疗卫生行业应急响应形势分析报告 脱敏板

声明 本文是学习2022医疗卫生行业网络安全分析报告. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 医疗卫生行业应急响应形势分析 2021年1-12月&#xff0c;奇安信集团安服团队共参与和处置全国范围内医疗卫生行业网络安全应急响应事件84起&#xf…

is not defined at HTMLInputElement.onclick

vue项目中一小部分功能想要使用原生的onclick 事件&#xff0c;发现报错Uncaught ReferenceError: 函数名 is not defined at HTMLInputElement.onclick搜索了相关blog&#xff0c;得出结论是onclick事件调用的方法必须是全局变量或者说是window的方法解决方法&#xff1a;将cl…

leetcode:43. 字符串相乘(附加一些C++string其他小练习)

目录 一.leetcode&#xff1a;43. 字符串相乘 1.问题描述 2.问题分析 3.问题求解 二. leetcode&#xff1a;541. 反转字符串 II 1.问题描述 2.题解 三. leetcode&#xff1a;125. 验证回文串 1.问题描述 2.双指针法求解 一.leetcode&#xff1a;43. 字符串相乘 43…

数据结构(括号匹配与表达式计算)

目录 括号配对 括号匹配算法 表达式计算 后缀式的计算 中缀式转后缀式 括号配对 编译器做语法检查的任务之一是检查符号是否配对&#xff0c;最简单的符号匹配问题是括号是否匹配&#xff0c;如开括号( 及{ 后面必须依次跟随相应的闭括号 }及 )。 如下段程序中的括号、引号…

谷歌竞价账户效果不好的原因?

很多外贸企业喜欢用谷歌竞价来推广自己的网站&#xff0c;提升自己的竞争力。是一种能很快看到效果的宣传方式。但是很多公司在谷歌竞价上投入了大量的资金&#xff0c;却收效甚微。为什么&#xff1f;下面我们来看看如何解决我们在google竞价推广中会遇到的一些问题。很多人在…

Linux的文件权限理解

目录 前言 1、用户、用户组、其他人 1.1用户、用户组、其他人之间的概念理解 1.2Linux系统中有用户身份与用户组记录的文件 2、Linux文件权限概念 第一列 第二列 第三列 第四列 第五列 第六列 第七列 Linux文件权限的重要性 3、Linux的目录与文件的权限意义 权限…

计算机图形学 第5章 二维变换与裁剪到Cohen-Sutherland直线裁剪算法

目录学习目标前驱知识规范化齐次坐标二维几何变换矩阵物体变换与坐标变换二维几何变换二维图形基本几何变换矩阵平移变换矩阵比例变换矩阵旋转变换矩阵反射变换矩阵错切变换矩阵二维仿射变换二维复合变换相对于任意方向的二维几何变换二维图形裁剪世界坐标系2.用户坐标系观察坐…

VSCode中设置Python语言自动格式化的方案

安装Python扩展 在VSCode的扩展&#xff08;Externsions&#xff09;中使用下面命令检索Python扩展 category:debuggers Python 打开一个Python文件&#xff0c;可以在VSCode的右下角看到运行环境。 安装PEP8 python3.10 -m pip install -U autopep8 安装Flake8 python3.10 …

上百个数字经济新场景 低代码完美搭建 实现项目落地

数字经济 自人类社会进入信息时代以来&#xff0c;数字技术的快速发展和广泛应用衍生出数字经济(Digital Economy)。与农耕时代的农业经济&#xff0c;以及工业时代的工业经济大有不同&#xff0c;数字经济是一种新的经济、新的动能&#xff0c;新的业态&#xff0c;其引发了社…

MicroBlaze系列教程(3):AXI_TIMER的使用

文章目录 @[toc]AXI_TIMER简介常用函数使用示例参考资料工程下载本文是Xilinx MicroBlaze系列教程的第3篇文章。 AXI_TIMER简介 AXI_TIMER支持两路可编程32位计数器,可以配置为中断、捕获、PWM模式,两个32位计数器可以级联为一个64位计数器。 IP核支持的最高频率: 常用…