美文网首页
C语言 IO操作

C语言 IO操作

作者: 放肆滴微笑 | 来源:发表于2020-10-28 17:23 被阅读0次

    读取文件

    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 = "hchmily@sina.com,程华才,学清路 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操作

          本文链接:https://www.haomeiwen.com/subject/jrkdactx.html