C语言 IO操作

读取文件

int main(int argc, const char * argv[]) {
    char * path = "/Users/wangxin/Documents/work/Android/ndk/c/C/friends.txt";
    //打开
    FILE *fp = fopen(path,"r");
    if (fp == NULL){
        printf("文件打开失败...");
        return 0;
    }
    //读取
    char buff[50]; //缓冲
    //n = 50所指向的输入流中读取 n - 1 个字符。它会把读取的字符串复制到缓冲区 buf,并在最后追加一个 null 字符来终止字符串。
    while (fgets(buff,50,fp)){
        printf("%s",buff);
    }
    //关闭
    fclose(fp);

    return 0;
}

写入文本文件

void main(){
 char *path = "/Users/wangxin/Documents/work/Android/ndk/c/C/friends_new.txt";
 //打开
 FILE *fp = fopen(path, "w");
 char *text = "[email protected],程华才,学清路 8\n号科技财富中心 A";
 fputs(text,fp);
 
 //关闭流
 fclose(fp);
 }

文件复制

  • 计算机的文件存储在物理上都是二进制
  • 文本文件和二进制之分,其实是一个逻辑之分
  • C读写文本文件与二进制文件的差别仅仅体现在回车换行符
  • 写文本时,每遇到一个'\n',会将其转换成'\r\n'(回车换行)
  • 读文本时,每遇到一个'\r\n',会将其转换成'\n'
 void main(){
 char *read_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/liuyan.png";
 char *write_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/liuyan_new.png";
 //读的文件 b字符表示操作二进制文件binary
 FILE *read_fp = fopen(read_path, "rb");
 //写的文件
 FILE *write_fp = fopen(write_path, "wb");
 
 //复制
 int buff[50]; //缓冲区域
 int len = 0; //每次读到的数据长度
 while ((len = fread(buff, sizeof(int), 50, read_fp)) != 0){
 //将读到的内容写入新的文件
 fwrite(buff,sizeof(int),len,write_fp);
 }
 //关闭流
 fclose(read_fp);
 fclose(write_fp);
 }

获取文件的大小

void main(){
 char *read_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/liuyan_new.png";
 FILE *fp = fopen(read_path, "r");
 //重新定位文件指针
 //SEEK_END文件末尾,0偏移量
 fseek(fp,0,SEEK_END);   // 相当于文件,从0位置到结束位置,这个函数可以取文件的任意开始和结束位置
 //返回当前的文件指针,相对于文件开头的位移量
 long filesize = ftell(fp);
 printf("%d\n",filesize);
 }

文本文件加解密

异或规则:1^1=0, 0^0=0, 1^0=1, 0^1=1 同为0,不同为1
所以每个字符和一个数字进行异或操作,操作第一次加密,第二次解密

//加密
 void crpypt(char normal_path[],char crypt_path[]){
 //打开文件
 FILE *normal_fp = fopen(normal_path, "r");
 FILE *crypt_fp = fopen(crypt_path, "w");
 //一次读取一个字符
 int ch;
 while ((ch = fgetc(normal_fp)) != EOF){ //End of File
 //写入(异或运算)
 fputc(ch ^ 9,crypt_fp);
 }
 //关闭
 fclose(crypt_fp);
 fclose(normal_fp);
 }
 
 //解密
 void decrpypt(char crypt_path[], char decrypt_path[]){
 //打开文件
 FILE *normal_fp = fopen(crypt_path, "r");
 FILE *crypt_fp = fopen(decrypt_path, "w");
 //一次读取一个字符
 int ch;
 while ((ch = fgetc(normal_fp)) != EOF){ //End of File
 //写入(异或运算)
 fputc(ch ^ 9, crypt_fp);
 }
 //关闭
 fclose(crypt_fp);
 fclose(normal_fp);
 
 }
void main(){
    char *normal_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/friends.txt";
    char *crypt_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/friends_crypt.txt";
    char *decrypt_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/friends_decrypt.txt";
    
//    crpypt(normal_path, crypt_path);
    //解密
    decrpypt(crypt_path, decrypt_path);
}

二进制文件加解密

读取二进制文件中的数据时,一个一个字符读取,再给每个字符和密码进行与操作

// 加密
void crpypt(char normal_path[], char crypt_path[],char password[]){
 //打开文件
 FILE *normal_fp = fopen(normal_path, "rb");
 FILE *crypt_fp = fopen(crypt_path, "wb");
 //一次读取一个字符
 int ch;
 int i = 0; //循环使用密码中的字母进行异或运算
 int pwd_len = strlen(password); //密码的长度
 while ((ch = fgetc(normal_fp)) != EOF){ //End of File
 //写入(异或运算)
 fputc(ch ^ password[i % pwd_len], crypt_fp);
 i++;
 }
 //关闭
 fclose(crypt_fp);
 fclose(normal_fp);
 }
 
 //解密
 void decrpypt(char crypt_path[], char decrypt_path[],char password[]){
 //打开文件
 FILE *normal_fp = fopen(crypt_path, "rb");
 FILE *crypt_fp = fopen(decrypt_path, "wb");
 //一次读取一个字符
 int ch;
 int i = 0; //循环使用密码中的字母进行异或运算
 int pwd_len = strlen(password); //密码的长度
 while ((ch = fgetc(normal_fp)) != EOF){ //End of File
 //写入(异或运算)
 fputc(ch ^ password[i % pwd_len], crypt_fp);
 i++;
 }
 //关闭
 fclose(crypt_fp);
 fclose(normal_fp);
 
 }
 
 void main(){
 char *normal_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/liuyan.png";
 char *crypt_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/liuyan_crypt.png";
 char *decrypt_path = "/Users/wangxin/Documents/work/Android/ndk/c/C/liuyan_decrypt.png";
 
// crpypt(normal_path, crypt_path,"iloveqq");
 //解密
 decrpypt(crypt_path, decrypt_path,"iloveqq");
 }

文件拆分

整除
文件大小:90,分成9个文件,每个文件10
不整除
文件大小:110,分成9个文件,
前(9-1)个文件为(110/(9-1))=13
最后一个文件(110%(9-1))=6

//java
String SD_CARD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath();
// 文件拆分
String path = SD_CARD_PATH + File.separatorChar+ "test.mp4";
String path_pattern = SD_CARD_PATH +File.separatorChar+ "test_%d.mp4";
NDKFileUtils.diff(path, path_pattern, 3);

// 文件合并
String path_pattern = SD_CARD_PATH +File.separatorChar+ "test_%d.mp4";
String merge_path = SD_CARD_PATH +File.separatorChar+ "test_merge.mp4";
NDKFileUtils.patch(path_pattern, 3, merge_path);

// C 代码
//获取文件大小
long get_file_size(const char *path) {
    FILE *fp = fopen(path, "rb");
    fseek(fp, 0, SEEK_END);
    return ftell(fp);
}

JNIEXPORT void JNICALL
Java_com_wx_file_1patch_NDKFileUtils_diff(
        JNIEnv *env,
        jclass jcls,
        jstring path_jstr,  // 要拆分的文件路径
        jstring path_pattern_jstr, // 拆分后的文件路径
        jint file_num //拆分成几个文件
) {

    const char *path = (*env)->GetStringUTFChars(env, path_jstr, 0);
    const char *path_patter = (*env)->GetStringUTFChars(env, path_pattern_jstr, 0);

    //得到分割之后的子文件的路径列表
    char **patches = malloc(sizeof(char *) * file_num);
    int i = 0;
    for (; i < file_num; ++i) {
        patches[i] = malloc(sizeof(char *) * 100);
        sprintf(patches[i], path_patter, (i + 1));
        LOGD("patch path :%s", patches[i]);
    }
//    int sprintf(char* str, const char* __fmt, ...)
//    str -- 这是指向一个字符数组的指针,该数组存储了 C 字符串。
//      __fmt 这是字符串,包含了要被写入到字符串 str 的文本。它可以包含嵌入的 format 标签,
//      也就是给字符数组赋值,那个字符串


    //不断读取path文件,循环写入file_num个文件中
    //  整除
    //  文件大小:90,分成9个文件,每个文件10
    //  不整除
    //  文件大小:110,分成9个文件,
    //  前(9-1)个文件为(110/(9-1))=13
    //  最后一个文件(110%(9-1))=6
    int filesize = get_file_size(path);
    FILE *fpr = fopen(path, "rb");
    //整除
    if (filesize % file_num == 0) {
        //单个文件大小
        int part = filesize / file_num;
        i = 0;
        //逐一写入不同的分割子文件中
        for (; i < file_num; i++) {
            FILE *fpw = fopen(patches[i], "wb");
            int j = 0;
            for (; j < part; j++) {
                //边读边写
                fputc(fgetc(fpr), fpw);
            }
            fclose(fpw);
        }
    } else {
        //不整除
        int part = filesize / (file_num - 1);
        i = 0;
        //逐一写入不同的分割子文件中
        for (; i < file_num - 1; i++) {
            FILE *fpw = fopen(patches[i], "wb");
            int j = 0;
            for (; j < part; j++) {
                //边读边写
                fputc(fgetc(fpr), fpw);
            }
            fclose(fpw);
        }
        //the last one
        FILE *fpw = fopen(patches[file_num - 1], "wb");
        i = 0;
        for (; i < filesize % (file_num - 1); i++) {
            fputc(fgetc(fpr), fpw);
        }
        fclose(fpw);
    }

    //关闭被分割的文件
    fclose(fpr);

    //释放
    i = 0;
    for (; i < file_num; i++) {
        free(patches[i]);
    }
    free(patches);

    (*env)->ReleaseStringUTFChars(env, path_jstr, path);
    (*env)->ReleaseStringUTFChars(env, path_pattern_jstr, path_patter);
}

JNIEXPORT void JNICALL
Java_com_wx_file_1patch_NDKFileUtils_patch(JNIEnv *env, jclass clazz, jstring path_pattern_jstr,
                                           jint file_num, jstring merge_path_jstr) {
//合并之后的文件
    const char* merge_path = (*env)->GetStringUTFChars(env,merge_path_jstr,NULL);
    //分割子文件的pattern
    const char* path_pattern = (*env)->GetStringUTFChars(env,path_pattern_jstr,NULL);

    //得到分割之后的子文件的路径列表
    char **patches = malloc(sizeof(char*) * file_num);
    int i = 0;
    for (; i < file_num; i++) {
        patches[i] = malloc(sizeof(char) * 100);
        //元素赋值
        //需要分割的文件:C://test.png
        //子文件:C://test_%d.png
        sprintf(patches[i], path_pattern, (i+1));
    }

    FILE *fpw = fopen(merge_path,"wb");
    //把所有的分割文件读取一遍,写入一个总的文件中
    i = 0;
    for(; i < file_num; i++){
        //每个子文件的大小
        int filesize = get_file_size(patches[i]);
        FILE *fpr = fopen(patches[i], "rb");
        int j = 0;
        for (; j < filesize; j++) {
            fputc(fgetc(fpr),fpw);
        }
        fclose(fpr);
    }
    fclose(fpw);

    //释放
    i = 0;
    for(; i < file_num; i++){
        free(patches[i]);
    }
    free(patches);

    (*env)->ReleaseStringUTFChars(env,path_pattern_jstr,path_pattern);
    (*env)->ReleaseStringUTFChars(env,merge_path_jstr,merge_path);
}

参考 https://www.runoob.com/cprogramming/c-file-io.html

你可能感兴趣的:(C语言 IO操作)