C语言文件操作

  • 1. 为什么使用文件
  • 2. 什么是文件
    • 2.1 程序文件
    • 2.2 数据文件
    • 2.3 文件名
  • 3. 文件的打开和关闭
    • 3.1 文件指针
    • 3.2 文件的打开和关闭
  • 4. 文件的顺序读写
    • 4.1 对比一组函数:
  • 5. 文件的随机读写
    • 5.1 fseek
    • 5.2 ftell
    • 5.3 rewind
  • 6. 文本文件和二进制文件
  • 7. 文件读取结束的判定
    • 7.1 被错误使用的feof
  • 8. 文件缓冲区
  • 本篇结束

1. 为什么使用文件

我们前面了解结构体时,写了通讯录的程序,当通讯录运行起来的时候,可以给通讯录中增加、删除数据,此时数据是存放在内存中,当程序退出的时候,通讯录中的数据自然就不存在了,等下次运行通讯录程序的时候,数据又得重新录入,如果使用这样的通讯录就很难受。(前面我已经把通讯录完善了)
我们在想既然是通讯录就应该把信息记录下来,只有我们自己选择删除数据的时候,数据才不复存在。
这就涉及到了数据持久化的问题,我们一般数据持久化的方法有,把数据存放在磁盘文件、存放到数据库等方式。
使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化。

2. 什么是文件

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

2.1 程序文件

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

2.2 数据文件

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

本章讨论的是数据文件。
在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。
其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件。

2.3 文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
例如: c:\code\test.txt
为了方便起见,文件标识常被称为文件名

3. 文件的打开和关闭

3.1 文件指针

缓冲文件系统中,关键的概念是**“文件类型指针”,简称“文件指针”**。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名
字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统
声明的,取名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指向某个文件的文件信息区(是一个结构体变
量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联
的文件。

比如:

3.2 文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件
注意:关闭文件是很有必要的,因为一个程序中打开的文件数量是有限的。
在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指
针和文件的关系。
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。

//打开文件
FILE * fopen ( const char * filename, const char * mode );//第一个参数是打开什么文件,文件如果没有路径,默认路径就是你编译器中你源文件的根目录下,第二个参数是以什么类型的方式打开这个文件
//关闭文件
int fclose ( FILE * stream );//参数是你打开文件的位置

打开方式如下:

文件使用方式 含义 如果指定文件不存在
“r”(只读) 为了输入数据,打开一个已经存在的文本文件 出错
“w”(只写) 为了输出数据,打开一个文本文件 建立一个新的文件
“a”(追加) 向文本文件尾添加数据 建立一个新的文件
“rb”(只读) 为了输入数据,打开一个二进制文件 出错
“wb”(只写) 为了输出数据,打开一个二进制文件 建立一个新的文件
“ab”(追加) 向一个二进制文件尾添加数据 出错
“r+”(读写) 为了读和写,打开一个文本文件 出错
“w+”(读写) 为了读和写,建议一个新的文件 建立一个新的文件
“a+”(读写) 打开一个文件,在文件尾进行读写 建立一个新的文件
“rb+”(读写) 为了读和写打开一个二进制文件 出错
“wb+”(读写) 为了读和写,新建一个新的二进制文件 建立一个新的文件
“ab+”(读写) 打开一个二进制文件,在文件尾进行读和写 建立一个新的文件

实例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{FILE* p = fopen("test.txt", "r");//以只读的方式打开test.txt这个文件if (p == NULL)//如果文件不存在就返回空指针{printf("%s", strerror(errno));//报错return 1;}fclose(p);//关闭文件p=NULL;
}

然后我们打卡源文件的根目录

发现没有test.txt这个文件,如果运行会怎么样呢?

这里会告诉你没有这个文件。
那么,我们换只写的方式:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{FILE* p = fopen("test.txt", "w");if (p == NULL){printf("%s", strerror(errno));return 1;}fclose(p);p=NULL;
}


没有报错,说明运行成功了。

看,这里就是我们自动创建的文件,当然里面啥也没有,因为我没有输入东西。

4. 文件的顺序读写

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

举几个例子:

写一个字符。
第一个参数是我们要写的字符,第二个参数是“流”,我们要把字符写到流里面去。(文件里面)
写入成功就返回写入的字符,如果错误就返回EOF。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{FILE* p = fopen("test.txt", "w");if (p == NULL){printf("%s", strerror(errno));return 1;}fputc('a', p);fclose(p);p = NULL;
}


没报错说明运行成功。

这样我们打开这个文件就有a这个字符了。

读一个字符。
参数是流的位置
如果读取的内容返回的是EOF就是读取失败,成功返回读取字符。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{FILE* p = fopen("test.txt", "r");if (p == NULL){printf("%s", strerror(errno));return 1;}/*fputc('a', p);*/int e = 0;if ((e = fgetc(p)) != EOF)//如果不是EOF就打印{printf("%c", e);}fclose(p);p = NULL;
}



写一行字符串。(这些函数的返回值都一样)
第一个参数是你要写的字符串,第二个参数是流。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{FILE* p = fopen("test.txt", "w");if (p == NULL){printf("%s", strerror(errno));return 1;}/*fputc('a', p);*//*int e = 0;if ((e = fgetc(p)) != EOF){printf("%c", e);}*/fputs("qweqwe", p);fclose(p);p = NULL;
}


运行成功(后面运行成功就不展示了)

之前还有一个a的字符,这时却没有了,因为只写的情况下,会清空里面的内容进行重写,这个阶段在打开文件的过程。

读一行字符串。
第一个参数是,读到的字符串,将会被放到str指向的这个位置,第二个参数是都几个字符,第三个是读取的位置流。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{FILE* p = fopen("test.txt", "r");if (p == NULL){printf("%s", strerror(errno));return 1;}/*fputc('a', p);*//*int e = 0;if ((e = fgetc(p)) != EOF){printf("%c", e);}*//*fputs("qweqwe", p);*/char arr[10] = { 0 };fgets(arr, 4, p);printf("%s", arr);fclose(p);p = NULL;
}


这里我们发现只有三个字符,这是因为第四个的位置上会放一个’\0‘,所以才打印出来三个。

格式化就代表可以输入结构体这种类型的信息了。
这个函数对比printf函数多了一个参数,是写入流的位置。
这里额外介绍一个函数:

这个也是报错的函数,参数是字符串,一般都是用来写是哪个地方出错了。
如果在里面输入fopen,那么这个函数一旦报错就会在屏幕上的打印出:

fopen:No such file or directory//多了原因和一个:号
这个函数还是很方便的。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{char name[20];int age;float weight;
};
int main()
{struct person s = { "baiye",25,75.0f };FILE* p = fopen("test.txt", "w");if (p == NULL){perror("fopen");return 1;}fprintf(p, "%s %d %f", s.name, s.age, s.weight);fclose(p);p = NULL;return 0;
}



这个能展示格式化信息。
也和scanf函数差不多,多出来的参数是第一个,也是流的位置。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{char name[20];int age;float weight;
};
int main()
{struct person s = { 0 };//我们并没有初始化任何值FILE* p = fopen("test.txt", "r");if (p == NULL){perror("fopen");return 1;}//fprintf(p, "%s %d %f", s.name, s.age, s.weight);fscanf(p, "%s %d %f", s.name, &(s.age), &(s.weight));printf("%s %d %f", s.name, s.age, s.weight);fclose(p);p = NULL;return 0;
}


我们从文件中读到了之前存入的信息。


流是这个,如果让外部设备和内存之间有联系,那么就需要各种类型的操作,每种不同的硬件都是不一样的,所以就有了流,我们只需要将信息放到流里面就可以读或写到各种外部设备上了。
在任何一个C语言的程序中,只要运行起来就会默认打开三个流:

FILEstdin - 标准输入流(键盘)
FILE
stdout - 便准输出流(屏幕)
FILE*stderr - 标准错误流(屏幕)


二进制方式写。
第一个参数是你要写的数据的地址,第二个参数是数据大小,第三个参数是一次写几个,第四个是流。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{char name[20];int age;float weight;
};
int main()
{struct person s = { "baiye",25,75.00 };FILE* p = fopen("test.txt", "wb");if (p == NULL){perror("fopen");return 1;}fwrite(&s, sizeof(struct person), 1, p);fclose(p);p = NULL;return 0;
}


因为是二进制写进去的,所以看不懂。

第一个参数是接收数据的位置,第二个是数据大小,第三个是个数,第四个是流。
返回参数是读取到的数据有多少个。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{char name[20];int age;float weight;
};
int main()
{struct person s = { 0 };FILE* p = fopen("test.txt", "rb");if (p == NULL){perror("fopen");return 1;}//fwrite(&s, sizeof(struct person), 1, p);fread(&s, sizeof(struct person), 1, p);printf("%s %d %f", s.name, s.age, s.weight);fclose(p);p = NULL;return 0;
}


这个函数就能看得懂,还是要用魔法打败魔法。

4.1 对比一组函数:

scanf/fscanf/sscanf
printf/fprintf/sprintf

第一个参数是你要存放的位置,后面的就和printf函数的参数没区别了。
把一个格式化的数据转换成字符串。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{char name[20];int age;float weight;
};
int main()
{struct person s = { "baiye",25,75.00 };char arr[100] = { 0 };sprintf(arr, "%s %d %f", s.name, s.age, s.weight);printf("%s", arr);//原理是让结构体里面的数据变成了这样子"baiye 25 75.00"return 0;
}



这个是把字符串获取格式化后放在第二个参数中。
第一次参数是你要读取字符串的位置,第二个参数是你要储存的位置。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct person
{char name[20];int age;float weight;
};
int main()
{struct person s = { "baiye",25,75.00 };struct person s1 = { 0 };char arr[100] = { 0 };sprintf(arr, "%s %d %f", s.name, s.age, s.weight);printf("字符串:%s\n", arr);//原理是让结构体里面的数据变成了这样子"baiye 25 75.00"sscanf(arr, "%s %d %f", s.name, &(s.age), &(s.weight));printf("格式化:%s %d %f\n", s.name, s.age, s.weight);return 0;
}

5. 文件的随机读写

我们文件指针最开始指向的都是第一个数据,读完第一个又指向第二个,那么怎么来控制指向呢?

5.1 fseek

根据文件指针的位置和偏移量来定位文件指针。

int fseek ( FILE * stream, long int offset, int origin );//第一个参数是流,第二个参数是偏移量,第三个参数是文件的起始位置


第一个是文件起始位置,第二个是当前文件指针的位置,第三个是文件的末尾位置。

例子:

#include <stdio.h>
int main()
{FILE* pFile;pFile = fopen("example.txt", "rb");//fputs("This is an apple.", pFile);fseek(pFile, 9, SEEK_SET);int i = fgetc(pFile);printf("%c\n", i);fseek(pFile, 2, SEEK_CUR);i = fgetc(pFile);printf("%c\n", i);fseek(pFile, -2, SEEK_END);i = fgetc(pFile);printf("%c\n", i);fclose(pFile);pFile = NULL;return 0;
}


这是文件里面的内容。

不要忘记字符串的末尾有个’\0‘。
这是结果。

5.2 ftell

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

long int ftell ( FILE * stream );//参数是流

例子:

#include <stdio.h>
int main()
{FILE* pFile;pFile = fopen("example.txt", "rb");//fputs("This is an apple.", pFile);fseek(pFile, 9, SEEK_SET);int i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));//打印偏移量的位置fseek(pFile, 2, SEEK_CUR);i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));fseek(pFile, -2, SEEK_END);i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));fclose(pFile);pFile = NULL;return 0;
}

5.3 rewind

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

void rewind ( FILE * stream );

例子:

#include <stdio.h>
int main()
{FILE* pFile;pFile = fopen("example.txt", "rb");//fputs("This is an apple.", pFile);fseek(pFile, 9, SEEK_SET);int i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));fseek(pFile, 2, SEEK_CUR);i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));fseek(pFile, -2, SEEK_END);i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));rewind(pFile);//让指针回到起始位置i = fgetc(pFile);printf("%c\n", i);printf("%d\n", ftell(pFile));fclose(pFile);pFile = NULL;return 0;
}


回到了起始位置。

6. 文本文件和二进制文件

根据数据的组织形式,数据文件被称为文本文件或者二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。
不考虑大小端的问题,下面是图解

测试代码

#include <stdio.h>
int main()
{int a = 10000;FILE* pf = fopen("test.txt", "wb");fwrite(&a, 4, 1, pf);//二进制的形式写到文件中fclose(pf);pf = NULL;return 0;
}


这里我的机器是小端存储的方式。
前面的00000000是编辑器的地址展示,不用管他。

7. 文件读取结束的判定

7.1 被错误使用的feof

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

  1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
    例如:
    fgetc 判断是否为 EOF .
    fgets 判断返回值是否为 NULL .
  2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
    例如:
    fread判断返回值是否小于实际要读的个数。//因为如果一共有9个字符,一次读5个,首先读了5个,那么再读一次剩下的4个字符返回值就是4,所以是小于。

正确的使用:
文本文件的例子:

#include <stdio.h>
#include <stdlib.h>
int main(void) {int c; // 注意:int,非char,要求处理EOFFILE* fp = fopen("test.txt", "r");if (!fp) {perror("File opening failed");return EXIT_FAILURE;}//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOFwhile ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环{putchar(c);}//判断是什么原因结束的if (ferror(fp))//判断是不是遇到文件错误了puts("I/O error when reading");//文件读取失败else if (feof(fp))puts("End of file reached successfully");//文件读取到末尾fclose(fp);
}

二进制文件的例子:

#include <stdio.h>
#include <stdlib.h>
enum { SIZE = 5 };
int main(void) {double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code == SIZE) //说明读到了5个元素{puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);putchar('\n');}else // error handling{ if (feof(fp))//看看是否是读到了文件末尾printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) //看看文件是否出错了{perror("Error reading test.bin");}}fclose(fp);
}

文本文件的例子

8. 文件缓冲区

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

测试代码:

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10环境测试
int main()
{FILE* pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)//注:fflush 在高版本的VS上不能使用了printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭文件的时候,也会刷新缓冲区pf = NULL;return 0;
}

刷新缓冲区会将缓冲区的内容都存到硬盘里。
这里可以得出一个结论:
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。

本篇结束

抽丝剥茧C语言(高阶)文件操作+练习相关推荐

  1. .pyc文件_python专题shutil高阶文件操作

    一 前言 如果读者读过知识追寻者其它文件相关专题操作,再来学习这篇高阶文件操作会让你的文件知识瞬间高涨一台阶:本篇文章有些函数作用给知识追寻中感觉是用来伪造信息的,相信如果做网络渗透的读者应该很喜欢这 ...

  2. Python 标准库之 shutil 高阶文件操作『详细』

    Python标准库之 shutil 高阶文件操作『详细』 文章目录 Python标准库之 shutil 高阶文件操作『详细』 一.Python shutil介绍

  3. C语言字符串、文件操作常用操作函数,

    C语言字符串常用操作函数 C语言字符串.文件操作常用操作函数 字符串输出 - puts() 字符串输入 - gets() 字符串比较 - strcmp() 字符串复制 - strcpy() 字符串连接 ...

  4. 【C 语言】文件操作 ( C 语言中的文件操作函数 | 磁盘与内存缓冲区 | 缓冲区工作机制 )

    文章目录 一.C 语言中的文件操作函数 二.磁盘与内存缓冲区 三.缓冲区工作机制 一.C 语言中的文件操作函数 读取 文本文件 可以使用 getc , fgets , fscanf 函数 , 向 文本 ...

  5. Unix/Linux环境C编程入门教程(41) C语言库函数的文件操作详解

     上一篇博客我们讲解了如何使用Linux提供的文件操作函数,本文主要讲解使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...

  6. 【C语言复习】C语言中的文件操作

    C语言中的文件操作 写在前面 文件操作 什么是文件 文件的分类 文件名 文件的操作 文件指针 文件的打开和关闭 文件的顺序读写 文件的随机读写 fseek ftell rewind feof 写在前面 ...

  7. C语言详解文件操作(一):文件操作基础概念、按照字符、按照行块、按照格式化和随机位置读写文件

    文章目录 一.文件操作基础概念 二.文件读写:按照字符方式读写 三.文件读写:按行和块读写 四.文件读写:格式化和随机位置 一.文件操作基础概念 C语言中的文件操作的好处:       一个文件通常是 ...

  8. C/C++语言入门篇 -- 文件操作

    最近实在是太忙了,这篇整整就推迟了1个月了,实在是对不起.之前本打算这个模块就结束了,文件操作就不写了,但是文件操作又是一个很重要的东西,而且也刚好能够总结之前我们学习的所有知识.同时也为了将文件操作 ...

  9. C语言目录和文件操作扩展

    文章目录 一.access库函数 二.stat库函数 1.stat结构体 2.stat库函数 三.utime库函数 四.rename库函数 五.remove库函数 六.课后作业 七.获取视频教程 八. ...

  10. C语言动态规划和文件操作练习——通讯录

    用C语言实现一个简单通讯录功能: 命令端输入对应指令可执行相应操作 可以实现增.删.查.改.排序.显示.一键清除等功能 每次输入的信息保存到txt文件中 每次打开通讯录自动加载已有的txt文件中的信息 ...

最新文章

  1. html宽度自适应怎么调整li超出隐藏,HTML篇之CSS样式——div ul li 嵌套后解决高度自适应方法...
  2. 【Python基础】Python安装第三方库太慢?配置好这个速度飞起
  3. win10系统中查找端口
  4. 广州 office365的开发者训练营交流活动简报
  5. A. Slackline Adventure(思维 + 莫比乌斯)(2018-2019 ACM-ICPC Brazil Subregional Programming Contest)
  6. python3.8.4rc1_Python3.8.4rc1 官方正式版
  7. C++之指针探究(九):结构体指针
  8. windows、Linux下nginx搭建集群
  9. python爬取了百万知乎,并做数据分析
  10. Xamarin For Visual Studio 3.7.165 完整离线破解版
  11. Linux chapter 5
  12. 《21天学通C语言(第7版)》一2.4 小 结
  13. SegNet论文笔记
  14. 高手实战!Windows 7开机加速完全攻略
  15. 微信扫一扫下载apk 微信直接下载APK(APP)的解决方案
  16. “HEAP:Invalid Address specified to RtlValidateHeap( 000D0000, 019FEF18 )错误
  17. 【OCM第18期开班】第18期11g OCM培训将于8月23日,晚20点在腾讯课堂开班,第1场考试免费培训!!!...
  18. redis 数据删除策略和逐出算法
  19. 网口up不起来问题排查
  20. 第1章第7节:如何通过大纲级别批量创建幻灯片 [PowerPoint精美幻灯片实战教程]

热门文章

  1. 一次关于亲子教育和少儿心理教育的讲座
  2. HOSTAPD ht_capab设置
  3. 修订版《三字经》 (2008 人教版)
  4. CMMI认证中的ATM
  5. Controller传入数组参数
  6. Docker容器之间的通信
  7. ajax请求415错误
  8. Java中Runtime类详细总结
  9. galera mysql ubuntu_Ubuntu14.04安装Mysql Galera Cluster
  10. touchslide配置参数