Как читать данные (двоичные или текстовые) в C из файла, написанного на Java? - PullRequest
0 голосов
/ 01 мая 2019

Запись на 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 () { один, два, три; 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(), в результате было бы легче идентифицировать целые числа / числа с плавающей запятой / строки.

Ответы [ 2 ]

1 голос
/ 01 мая 2019

Моя Java немного ржавая, но кажется, что вы записываете в файл три 4-байтовых целых числа, по порядку и в машинном порядке байтов (так что, вероятно, с прямым порядком байтов).Это означает, что ваш файл должен иметь (в шестнадцатеричном формате):

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 голосов
/ 02 мая 2019

Я понимаю, что fscanf читает поток символов, которые затем анализируются в соответствии с заданным форматом. Это означает, что мы должны написать файл на Java в символьном формате, который поддерживается C.

Вот что я сделал:

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. Другой момент заключается в том, что нам не нужно беспокоиться о ByteOrder, в котором значение ASCII записывается в файл. Похоже, что об этом позаботится 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* не была выделена память и все еще работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...