读取文件
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);
}
网友评论