上一篇是直接创建文件并写入内容。这次是读取文件内容,如果文件不存在则创建文件并写入内容。文件存在则修改内容。
直接修改下上一个demo, TestMmap类中增加一个native方法:
public native String testMmap2(String path);
同样,头文件也增加这个方法声明,代码略。 cpp文件增加这个函数实现:
cpp
extern "C"
JNIEXPORT jstring JNICALL Java_com_example_testmmap_TestMmap_testMmap2
(JNIEnv *env, jobject, jstring path) { // 判断文件不存在则创建文件,写入内容。存在则修改内容
const char *file_path = env->GetStringUTFChars(path, nullptr);
if (file_path == nullptr) {
return env->NewStringUTF("Failed to get file path");
}
long page_size = sysconf(_SC_PAGESIZE);
LOGI("当前系统内存页大小: %ld 字节", page_size);
// 打开文件(智能判断是否存在)
int fd = open(file_path, O_RDWR); // 先尝试以读写方式打开现有文件
bool is_new_file = false;
if (fd == -1) {
// 文件不存在 -> 创建新文件
LOGI("文件不存在,正在创建新文件...");
fd = open(file_path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); // O_CREAT表示文件不存在则创建
if (fd == -1) {
LOGI("创建文件失败: %s", file_path);
env->ReleaseStringUTFChars(path, file_path);
return env->NewStringUTF("Failed to create file");
}
// 设置初始大小为 4KB(对齐页大小)
if (ftruncate(fd, page_size) == -1) {
LOGI("设置文件大小失败");
close(fd);
env->ReleaseStringUTFChars(path, file_path);
return env->NewStringUTF("Failed to set file size");
}
is_new_file = true;
}
// 获取文件实际大小
struct stat st;
if (fstat(fd, &st) == -1) {
LOGI("获取文件状态失败");
close(fd);
env->ReleaseStringUTFChars(path, file_path);
return env->NewStringUTF("Failed to get file stat");
}
size_t file_size = st.st_size;
LOGI("当前文件大小: %zu 字节", file_size);
// 建立内存映射
void* mapped_mem = mmap(nullptr, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mapped_mem == MAP_FAILED) {
LOGI("mmap 映射失败");
close(fd);
env->ReleaseStringUTFChars(path, file_path);
return env->NewStringUTF("mmap failed");
}
// 读取内容并修改
char *content = (char *)mapped_mem;
if (is_new_file) {
// 新文件:写入初始内容
const char *initial_msg = "Vicky du,平安喜乐";
strcpy(content, initial_msg);
LOGI("新文件写入初始内容: %s", content);
} else {
// 现有文件:读取当前内容,然后修改
LOGI("修改前的内容: %s", content);
// 在末尾追加
std::string current_content(content);
std::string append_text = " love u ";
std::string new_content = current_content + append_text;
// 安全检查:确保新内容不超过文件大小(留一个字节给结尾的 '\0')
if (new_content.length() < file_size) {
strcpy(content, new_content.c_str());
LOGI("修改后的内容: %s", content);
} else {
// 空间不足时的降级方案:覆盖写一段新文本
const char *fallback_msg = "三人行,必有我师。";
strcpy(content, fallback_msg);
LOGI("内容过长,已覆盖写入: %s", content);
}
}
// 可选:强制刷盘
msync(mapped_mem, file_size, MS_SYNC);
// 清理资源
munmap(mapped_mem, file_size);
close(fd);
env->ReleaseStringUTFChars(path, file_path);
return env->NewStringUTF("mmap 读取并修改完成!");
}
MainActivity 写测试代码:
Kotlin
val path = filesDir.absolutePath + "/test2.txt"
val result = TestMmap().testMmap2(path)
Log.i("MainActivity", result ?: "Mmap result is null")
运行:

ok. 再一次运行:

ok. 可以看到文件内容修改成新的字符串了。