如何从用Java编写的文件中读取C中的数据(二进制或文本)?

问题描述 投票:-1回答:2

用Java编写:

File file = new File("abc");
try(FileOutputStream fos = new FileOutputStream(file)) {
    FileChannel outChannel = fos.getChannel();
    ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES*3).order(ByteOrder.nativeOrder());
    buffer.putInt(154);
    buffer.putint(98);
    buffer.putInt(6);
    outChannel.write(buffer);


    IntStream.rangeClosed(1,3).forEach((iter) -> {
        String reqString = (Integer.toString(iter) + "_string");
        byte[] bytes = reqString.getBytes(Charset.forName("US-ASCII"));
        ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length).order(ByteOrder.nativeOrder());
        byteBuffer.put(bytes);
        try {
            outChannel.write(byteBuffer);
        }
        catch(IOException ex) {
            ex.printStackTrace();
        }
    });
}   
catch(IOException ex) {
    ex.printStackTrace();
}

读C:int main(){int one,two,three; FILE * fp = fopen(“abc”,“r +”);

fscanf(fp,"%d",&one);
fscanf(fp,"%d",&two);
fscanf(fp,"%d",&three);

printf("%d %d %d",one,two,three);

char ch;
fread(&ch,sizeof(char),1,fp);
while(ch!= '\0') {
    printf("%c",ch);
    fread(&ch,sizeof(char),1,fp);
} 
return 0;
}

输出为:[output1]

我不明白我看到了什么。有三个值,没有一个是我写的。他们是记忆位置吗?还是垃圾值?

Java以哪种格式编写文件。因为,C读取底层平台的本机顺序,我试图使用ByteBuffer。如果我使用DataOutputService,我认为Java以“BIG_ENDIAN”格式写入,而C可能无法读取正确的值。

此外,如何在此方案中编写和读取字符串。 Java,默认情况下使用UTF-8,因此,我没有直接使用FileOutputStream,而是将它们转换为ASCII格式的字节,以便我可以逐个字符地读取它们。但是,没有显示输出。我什么时候可以使用fscanf(fp,"%s",string)(字符串是一个char数据类型变量,分配了足够的内存)*?


理想的解决方案是Java能够以特定顺序编写数据,C能够使用fscanf()读取数据,因此更容易识别整数/浮点数/字符串。

java c file text-files binaryfiles
2个回答
1
投票

我的Java有点生疏,但看起来你要写的文件是三个4字节整数,按顺序,并按机器顺序的字节(所以可能是little-endian)。这意味着你的文件应该是(十六进制):

9a 00 00 00 62 00 00 00 06 00 00 00

但是您的扫描预计会将数字视为以空格分隔的文本,例如(十六进制)

31 35 34 20 39 38 20 36 0a

你可能应该使用类似fread()的东西,它不会解析:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

目标应该是像int[3]这样的地址。


0
投票

据我所知,fscanf读取一个字符流,然后根据给定的格式进行解析。这意味着我们应该用C支持的字符格式用Java编写文件。

这就是我做的:

Java代码:

package scratchpad;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;

public class WriteClass {
    void writeFunction() {
        File defgFile = new File("/home/thor/Documents/ScratchPad/def.bin");
        try(FileOutputStream fos = new FileOutputStream(defgFile)){
            BufferedWriter bos = new BufferedWriter(new OutputStreamWriter(fos,StandardCharsets.US_ASCII));
            bos.write(Integer.toString(123));
            bos.newLine();
            bos.write(Integer.toString(96));
            bos.newLine();
            bos.write(Integer.toString(1));
            bos.newLine();
            bos.write("Water");
            bos.newLine();
            bos.write(Integer.toString(2));
            bos.newLine();
            bos.write("Forest");
            bos.newLine();

            bos.flush();
            bos.close();
        }
        catch(IOException ex) {
            Logger.getLogger(WriteClass.class.getName()).log(Level.SEVERE,"Can't open a new file",ex);
        }
    }
}

需要注意的重要一点是我使用OutputStreamWriter以ASCII格式编写文本文件。另一点是我们不必担心将ASCII值写入文件的ByteOrder。似乎Java正在处理它。

bos.newLine()是一种独立于平台的编写新线的方式。 bos.flush()是强制性的,否则数据将不会被写入。

C代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>   

int main() {

    FILE *fp = fopen("def.bin","r");
    int one,two,three;
    fscanf(fp,"%d",&one);
    fscanf(fp,"%d",&two);
    printf("%d\n%d\n",one,two);

    int index;
    fscanf(fp,"%d",&index);
    char* string;
    fscanf(fp,"%s",string); 
    printf("%d\n%s\n",classno,string);
    return 0;
}

我注意到字符串char*没有分配内存,仍然有效。

© www.soinside.com 2019 - 2024. All rights reserved.