前言:
第1节是笔者基于公司的“祖传”C语言操作模板上做相应修改的程序,当做自己以后使用C语言文件操作的模板。
第2节与第3节是笔者之前需要配合团队内的小伙伴做数据转换,他需要我将保存在.txt文件内的字符数据(十六进制)转换为二进制,也需要我将.Bin文件内的二进制数据转换为字符数据(十六进制)。当然这两节程序有很大的优化空间,弊端为每次读取数据的量太小,需要频繁IO操作,导致运行速度变得很慢。解决方法为使用malloc函数一次性将文件的内容读取到内存空间上,可大幅提高程序的运行速度。
第4节是笔者一直很好奇32位操作系统下的C语言的数据类型所占空间进行测试的例子,方便自己在后面的开发中准确的使用数据类型,不至于让数据小而空间大,或者数据大而空间小。
第5节是笔者想通过C语言为工程项目中修改配置文件中的参数,通过匹配配置文件中指定的变量去替换参数。但该节程序最后并未用于工程项目中,笔者想表达,C语言实现真的好麻烦,这就是更高级的编程语言强大之处。
第6节是笔者想为嵌入式Linux产品的开机Logo动态读取指定路径下的.ppm图片,原本考虑修改Kernel中显示Logo部分,将图片的数据写入相应的地方。但后面在内核源码中找不到内核编译时怎么将logo_linux_clut224.ppm编译为logo_linux_clut224.c的方法,不清楚.ppm文件是怎么将数据转化到struct linux_logo结构体中的clut和data成员,后面不得不放弃这种想法。但也让笔者改变思路,让驱动程序读取指定路径下的配置文件,让驱动定向运行。
第7节为应用层的常规文件操作。
第8节为获取挂载在文件系统下节点的存储情况。
第9节摘抄自《Linux程序设计 第4版》中第3、4节的C语言进行文件/目录、系统操作
第10节为记录程序运行的时间
下面的程序参考了网上的许多例子,测试可用,若需要使用,需要修改部分参数。
1. C语言文件操作的模板:
// 编译与运行命令:
// gcc xxxx.c -o xxxx
// ./xxxx
#include <stdio.h>
#include <string.h>
int OpenFile(char *ReadFile, char *WriteFile, unsigned int *FileLength,
FILE **fpRead, FILE **fpWrite);
void CloseFile(FILE *fpRead, FILE *fpWrite);
int FileOperation(unsigned int FileLength, FILE *fpRead, FILE *fpWrite);
int main(int argc, char *argv[])
{
char ReadFile[] = "ReadFile.txt";
char WriteFile[] = "WriteFile.txt";
FILE *fpRead = NULL, *fpWrite = NULL;
unsigned int FileLength = 0;
int ret = 0;
// 打开需要读、写的文件
ret = OpenFile(ReadFile, WriteFile, &FileLength, &fpRead, &fpWrite);
if(ret < 0)
{
return 0;
}
// 文件操作
FileOperation(FileLength, fpRead, fpWrite);
// 关闭文件
CloseFile(fpRead, fpWrite);
return 0;
}
int OpenFile(char *ReadFile, char *WriteFile, unsigned int *FileLength,
FILE **fpRead, FILE **fpWrite)
{
// 打开需要读的文件
*fpRead = fopen(ReadFile, "r+");
if(*fpRead == NULL)
{
printf("open %s error \n", ReadFile);
return -1;
}
// 打开需要写的文件
*fpWrite = fopen(WriteFile, "wb");
if(*fpWrite == NULL)
{
printf("open %s error \n", WriteFile);
fclose(*fpRead);
return -1;
}
// 将读文件指针定位于文件的末尾处,获取文件大小
fseek(*fpRead, 0, SEEK_END);
*FileLength = ftell(*fpRead);
printf("FileLength = %dB (%.2fMB) \n", *FileLength,
((double)*FileLength / (1024 * 1024)));
return 1;
}
void CloseFile(FILE *fpRead, FILE *fpWrite)
{
fclose(fpRead);
fclose(fpWrite);
}
int FileOperation(unsigned int FileLength, FILE *fpRead, FILE *fpWrite)
{
unsigned int i = 0;
unsigned char Array[3];
unsigned char CharLen = 2;
// 将读、写文件指针指向文件头
fseek(fpRead, 0, SEEK_SET);
fseek(fpWrite, 0, SEEK_SET);
// 进行文件读写
for(i = 0; i < FileLength; i += 2)
{
if((i != 0) && (i % 16 == 0))
{
fwrite("\n", sizeof(unsigned char), 1, fpWrite);
}
memset(Array, '\0', sizeof(Array));
fread(Array, sizeof(unsigned char), CharLen, fpRead);
fwrite(Array, sizeof(unsigned char), CharLen, fpWrite);
fwrite(" ", sizeof(unsigned char), 1, fpWrite);
}
return 1;
}
FILE结构体:
// 位于stdio.h,笔者在Linux底下找不到定义FILE结构体,只在Visual Studio内找到了定义
// 不同编译器下的FILE结构体定义不一样
// FILE结构是间接地操作系统的文件控制块 (FCB)来实现对文件的操作
#ifndef _FILE_DEFINED
struct _iobuf {
char *_ptr; // 文件输入的下一个位置
int _cnt; // 当前缓冲区的相对位置
char *_base; // 指基础位置(即是文件的其始位置)
int _flag; // 文件标志
int _file; // 应该是文件描述符,进入打开文件列表索引的整数
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
#define _FILE_DEFINED
#endif
2. 将字符(十六进制)转成二进制(C语言的文件操作):
// 编译与运行命令:
// gcc xxxx.c -o xxxx -lm
// ./xxxx
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <unistd.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
char FilePath[] = "/mnt/hgfs/XXXX/";
char ReadFile[] = "File";
char WriteFile[] = "FileConvert";
char TxtUnit[] = ".txt";
char BinUnit[] = ".bin";
char ReadFilePath[80], WriteFilePath[80];
char ClearWriteFileCmd[160], TxtToJPEGCmd[160];
unsigned int FileLength = 0;
char array[4];
unsigned char DataBin = 0;
unsigned char DataTemp = 0;
int i = 0, j = 0;
FILE *fpRead = NULL, *fpWrite = NULL;
unsigned int NumRead = 0, NumWrite = 0;
unsigned int DataCount = 0;
int CharLen = 2; // 每次读取文件的两个字符
memset(ReadFilePath, 0, 80 * sizeof(char));
memset(WriteFilePath, 0, 80 * sizeof(char));
memset(ClearWriteFileCmd, 0, 160 * sizeof(char));
memset(TxtToJPEGCmd, 0, 160 * sizeof(char));
sprintf(ReadFilePath, "%s%s%s", FilePath, ReadFile, TxtUnit);
sprintf(WriteFilePath, "%s%s%s", FilePath, WriteFile, TxtUnit);
sprintf(ClearWriteFileCmd, "dd if=/dev/null of=%s%s%s", FilePath, WriteFile, TxtUnit);
sprintf(TxtToJPEGCmd, "mv %s%s%s %s%s%s", FilePath, WriteFile, TxtUnit, FilePath, WriteFile, BinUnit);
// 打开需要读的文件
fpRead = fopen(ReadFilePath , "r+");
if(fpRead == NULL)
{
printf("Open %s error \n", ReadFilePath);
return -1 ;
}
// 打开需要写的文件
fpWrite = fopen(WriteFilePath , "wb");
if(fpWrite == NULL)
{
printf("Open %s error \n", WriteFilePath);
return -1 ;
}
printf("Open %s Success \n", ReadFilePath);
printf("Open %s Success \n", WriteFilePath);
system(ClearWriteFileCmd);
// 定位于文件的末尾处,获取文件大小
fseek(fpRead, 0, SEEK_END);
FileLength = ftell(fpRead);
printf("FileLength = %d (%.2fK %.2fM) \n", FileLength, ((double)FileLength / 1024), ((double)FileLength / 1024 / 1024));
// 将文件指针指向文件头
fseek(fpRead, 0, SEEK_SET);
fseek(fpWrite, 0, SEEK_SET);
NumRead = 0;
NumWrite = 0;
while(NumRead < FileLength)
{
memset(&array, '\0', 4 * sizeof(char));
fseek(fpRead, NumRead, SEEK_SET);
fread(array, sizeof(char), CharLen, fpRead);
// 判断取出的值是否为换行符、空格、制表符、回车符
//if((array[0] == '\n') || (array[0] == ' ') || (array[0] == '\t') || (array[0] == '\r'))
if(array[0] <= ' ')
{
NumRead += (1 * sizeof(char));
continue ;
}
NumRead += (CharLen * sizeof(char));
// 下面这句话不能写,会大大拖慢速度,运行速度降低150倍左右
//fseek(fpWrite, NumWrite, SEEK_SET);
// 字符转为数据
for(DataBin = 0 , j = 0 ; j < CharLen ; j ++)
{
DataTemp = array[j] ;
if((DataTemp >= '0') && (DataTemp <= '9')) DataTemp = DataTemp - '0';
else if((DataTemp >= 'a') && (DataTemp <= 'z')) DataTemp = (DataTemp - 'a' + 10);
else if((DataTemp >= 'A') && (DataTemp <= 'Z')) DataTemp = (DataTemp - 'A' + 10);
//DataBin += (DataTemp * pow(16, (CharLen - 1 - j)));
DataBin += (DataTemp << (4 * (CharLen - 1 - j)));
}
fwrite(&DataBin, sizeof(char), 1, fpWrite);
NumWrite += (1 * sizeof(char));
DataCount ++ ;
}
fclose(fpRead);
fclose(fpWrite);
system(TxtToJPEGCmd);
return 0 ;
}
3. 将二进制转成字符(十六进制)(C语言的文件操作):
// 编译与运行命令:
// gcc xxxx.c -o xxxx -lm
// ./xxxx
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#