C 中的 fprintf() 在通过 Java 本机接口调用时生成垃圾文件名
fprintf() in C makes garbage filename when called via Java Native Interface
我正在做一个 Java 程序,它通过 JNI 调用一些 C 函数。我有一种情况,我在 C 中收集了一堆计算机能量读数并想将它们写入文件。理想情况下,我想使用 fprintf()
,而不是将所有数据格式化为字符串,通过 JNI 接口将其传递到 Java,然后以 Java 的方式写入文件,但这似乎效率低了很多。
唯一的问题是当我在 C 中执行 fprintf()
时,我得到的输出文件有一个垃圾名称。绝对不是我提供的文件名。
alejandro@alejandro-ThinkPad-E15:~/throwawayfiles$ ls
''$'0052\a'
虽然文件的内容符合我的预期。我也在 C 中调用了这个函数并且它工作得很好,唯一的问题是当我方便从 Java 程序调用它时。有没有一种方法可以确保输出文件具有我真正想要的名称?或者这只是我必须处理的 JNI 问题之一。就像我说的,计划 B 是将所有数据放在一个字符串中,将其发送到 java,然后从那里写入文件,但这很慢,而且我不想写代码:)
谢谢!
用于写入文件的代码。我正在处理一个收集能量读数的数据结构 AsyncEnergyMonitor。所有的读取和数据存储都是在 C 中完成的,但在 Java 程序的更大上下文中都得到了促进。
private native static void writeToFileFromC(String filePath);
public void writeToFile(String filePath)
{
writeToFileFromC(filePath);
}
JNIEXPORT void JNICALL
Java_jrapl_AsyncEnergyMonitorCSide_writeToFileFromC(JNIEnv* env,
jclass jcls, const char* filepath)
{
writeToFile(monitor, filepath);
}
这里是最初打开文件的地方,我在 header 行中写下。
void writeToFile(AsyncEnergyMonitor *monitor, const char* filepath){
FILE * outfile = (filepath) ? fopen(filepath,"w") : stdout;
fprintf(outfile,"samplingRate: %d milliseconds\n",monitor->samplingRate);
fprintf(outfile,"socket,dram,gpu,core,pkg,timestamp(usec since epoch)\n");
if (USING_DYNAMIC_ARRAY)
writeToFile_DynamicArray(outfile, monitor->samples_dynarr);
if (USING_LINKED_LIST)
writeToFile_LinkedList(outfile, monitor->samples_linklist);
if (filepath) fclose(outfile);
}
下面是我用来写入其余数据的两个函数,具体取决于数据是存储在链表还是动态数组中。
void
writeToFile_DynamicArray(FILE* outfile, DynamicArray* a) {
for (int i = 0; i < a->nItems; i++) {
EnergyStats current = a->items[i];
char csv_string[512];
energy_stats_csv_string(current, csv_string);
fprintf(outfile,"%s\n",csv_string);
}
}
void
writeToFile_LinkedList(FILE* outfile, LinkedList* l) {
LinkNode* current = l->head;
while(current != NULL) {
int upperbound = (current == l->tail) ?
(l->nItemsAtTail) : (NODE_CAPACITY);
for (int i = 0; i < upperbound; i++) {
char ener_string[512];
energy_stats_csv_string(current->items[i], ener_string);
fprintf(outfile,"%s\n",ener_string);
}
current = current->next;
}
}
我忘了将文件路径名称从 Java 字符串显式转换为 C 字符串。与从 C 写入文件无关。只是做了一个垃圾字符串名称,因为我没有转换
JNIEXPORT void JNICALL
Java_jrapl_AsyncEnergyMonitorCSide_writeToFileFromC(JNIEnv* env,
jclass jcls, const char* filepath)
{
writeToFile(monitor, filepath);
}
已将其修复为
JNIEXPORT void JNICALL
Java_jrapl_AsyncEnergyMonitorCSide_writeToFileFromC(JNIEnv* env, jclass jcls,
jstring jstringFilepath)
{
const char* filepath = (*env)->GetStringUTFChars(env, jstringFilepath, NULL);
writeToFile(monitor, filepath);
(*env)->ReleaseStringUTFChars(env, jstringFilepath, filepath);
}
一切顺利。
我正在做一个 Java 程序,它通过 JNI 调用一些 C 函数。我有一种情况,我在 C 中收集了一堆计算机能量读数并想将它们写入文件。理想情况下,我想使用 fprintf()
,而不是将所有数据格式化为字符串,通过 JNI 接口将其传递到 Java,然后以 Java 的方式写入文件,但这似乎效率低了很多。
唯一的问题是当我在 C 中执行 fprintf()
时,我得到的输出文件有一个垃圾名称。绝对不是我提供的文件名。
alejandro@alejandro-ThinkPad-E15:~/throwawayfiles$ ls
''$'0052\a'
虽然文件的内容符合我的预期。我也在 C 中调用了这个函数并且它工作得很好,唯一的问题是当我方便从 Java 程序调用它时。有没有一种方法可以确保输出文件具有我真正想要的名称?或者这只是我必须处理的 JNI 问题之一。就像我说的,计划 B 是将所有数据放在一个字符串中,将其发送到 java,然后从那里写入文件,但这很慢,而且我不想写代码:)
谢谢!
用于写入文件的代码。我正在处理一个收集能量读数的数据结构 AsyncEnergyMonitor。所有的读取和数据存储都是在 C 中完成的,但在 Java 程序的更大上下文中都得到了促进。
private native static void writeToFileFromC(String filePath);
public void writeToFile(String filePath)
{
writeToFileFromC(filePath);
}
JNIEXPORT void JNICALL
Java_jrapl_AsyncEnergyMonitorCSide_writeToFileFromC(JNIEnv* env,
jclass jcls, const char* filepath)
{
writeToFile(monitor, filepath);
}
这里是最初打开文件的地方,我在 header 行中写下。
void writeToFile(AsyncEnergyMonitor *monitor, const char* filepath){
FILE * outfile = (filepath) ? fopen(filepath,"w") : stdout;
fprintf(outfile,"samplingRate: %d milliseconds\n",monitor->samplingRate);
fprintf(outfile,"socket,dram,gpu,core,pkg,timestamp(usec since epoch)\n");
if (USING_DYNAMIC_ARRAY)
writeToFile_DynamicArray(outfile, monitor->samples_dynarr);
if (USING_LINKED_LIST)
writeToFile_LinkedList(outfile, monitor->samples_linklist);
if (filepath) fclose(outfile);
}
下面是我用来写入其余数据的两个函数,具体取决于数据是存储在链表还是动态数组中。
void
writeToFile_DynamicArray(FILE* outfile, DynamicArray* a) {
for (int i = 0; i < a->nItems; i++) {
EnergyStats current = a->items[i];
char csv_string[512];
energy_stats_csv_string(current, csv_string);
fprintf(outfile,"%s\n",csv_string);
}
}
void
writeToFile_LinkedList(FILE* outfile, LinkedList* l) {
LinkNode* current = l->head;
while(current != NULL) {
int upperbound = (current == l->tail) ?
(l->nItemsAtTail) : (NODE_CAPACITY);
for (int i = 0; i < upperbound; i++) {
char ener_string[512];
energy_stats_csv_string(current->items[i], ener_string);
fprintf(outfile,"%s\n",ener_string);
}
current = current->next;
}
}
我忘了将文件路径名称从 Java 字符串显式转换为 C 字符串。与从 C 写入文件无关。只是做了一个垃圾字符串名称,因为我没有转换
JNIEXPORT void JNICALL
Java_jrapl_AsyncEnergyMonitorCSide_writeToFileFromC(JNIEnv* env,
jclass jcls, const char* filepath)
{
writeToFile(monitor, filepath);
}
已将其修复为
JNIEXPORT void JNICALL
Java_jrapl_AsyncEnergyMonitorCSide_writeToFileFromC(JNIEnv* env, jclass jcls,
jstring jstringFilepath)
{
const char* filepath = (*env)->GetStringUTFChars(env, jstringFilepath, NULL);
writeToFile(monitor, filepath);
(*env)->ReleaseStringUTFChars(env, jstringFilepath, filepath);
}
一切顺利。