简体   繁体   中英

How to read data (either binary or text) in C from a file written in Java?

Writing in 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();
}

Reading in 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;
}

To which the output is: [输出1]

I don't understand what I see. There are three value and none of which were written by me. Are they memory locations? or Garbage values?

In which format does the Java write a file. Since, C reads in native order of the underlying platform I tried to use ByteBuffer. If I use DataOutputService, I though that the Java writes in `BIG_ENDIAN' format and C might not be able to read a proper value.

Also, how do I write and read a string in this scenario. Java, by default uses UTF-8, hence, I didn't use FileOutputStream directly, instead converted they into bytes of ASCII format so that I can read them character by character. But, no output is shown. When can I use fscanf(fp,"%s",string) (string is a char datatype variable with sufficient memory allocated)*?


Ideal solution would be where Java is able to write Data in particular order and C is able to read it using fscanf() , as a result it would be easier to identify integers/floats/strings.

My Java is kind of rusty, but it seems what you're writing to the file is three 4-byte integers, in sequence, and in machine order of bytes (so probably little-endian). That means your file should have (in hex):

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

But your scan expected to see the numbers as space-separated text, eg (in hex)

31 35 34 20 39 38 20 36 0a

You should probably use something like fread() , which doesn't do parsing:

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

and the target should be the address of something like an int[3] .

I understand that fscanf reads a stream of characters which are then parsed according to the given format. Which means we should write the file in Java in character format which is supported by C.

This is what I did:

Java code:

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);
        }
    }
}

Important thing to notice is that I have used OutputStreamWriter to write text file in ASCII format. Another point is that we need not worry about the ByteOrder in which an ASCII value is written to a file. It seems like Java is taking care of it.

The bos.newLine() is platform independent way to write a new line. bos.flush() is mandatory or else the data won't be written.

The C code:

#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;
}

I have noticed that string char* was not allocated memory and still worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM