试图通过管道将 C 中生成的数据传递给 Java 类。传递变量在java中出现空白而不是有数据

Posted

技术标签:

【中文标题】试图通过管道将 C 中生成的数据传递给 Java 类。传递变量在java中出现空白而不是有数据【英文标题】:Trying to pass data generated in C to Java class via pipe. Pass variable is coming up blank in java instead of having data 【发布时间】:2018-06-01 01:56:47 【问题描述】:

有 6 个文件/类:mainLaptop、Send、c_app、StreamTest、make file 和 ap.text。

我正在尝试获取在 c 文件中处理的数据并将其传递给我的 java 文件中的变量。在此处遵循本教程的“带字符串的管道”部分:http://www.jonathanbeard.io/tutorials/CtoJava

首先我打开终端并输入

1 make StreamTest
2 make c_app
3 java -cp . StreamTest
4 ./c_app

执行时,我看到“JAVA SIDE!!”接下来是终端中c进程的总数,数量和平均值(以及由于我的修改而导致的一些错误)

然后在eclipse中我在eclipse中运行StreamTest

Eclipse 输出这个

JAVA SIDE: 
 [x] Sent ''Leonardo
 [x] Sent ''Raphael
 [x] Sent ''Donatello
 [x] Sent ''Michelangelo

但我需要它来输出这个

JAVA SIDE: 
 [x] Sent 'Total: 4953, Integers: 1000, Average: 4.9530'Leonardo
 [x] Sent 'Total: 4953, Integers: 1000, Average: 4.9530'Raphael
 [x] Sent 'Total: 4953, Integers: 1000, Average: 4.9530'Donatello
 [x] Sent 'Total: 4953, Integers: 1000, Average: 4.9530'Michelangelo

这里是c代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>

#define DEBUG 0
#define BUFFER 4096

//open ap.txt for text input
static const char* exFile = "ap.txt";
static char inputBuffer[BUFFER];

int main(int argc, const char** argv)

    FILE *fp = fopen(exFile,"r");
    /*check and see if the pointer is null in otherwords see if the memory 
      location refered to by fp is set...no memory location should be zero 
      if you want to reference it   
      Here are some good ways to do this other than the way I did it below:
      if(!fp) do error
      if(fp == NULL) do error
      and then there's the way I did it below
     */

    if(fp == 0)
        fprintf(stderr,"Null pointer exception, check file name.\n");
        exit(-1);
    

    //check and see if an error occured during open
    const int err = ferror(fp);
    if(err != 0)
        /* void perror(const char* err) returns specific error message to string attached. */
        const char* errMessage = strcat("Something bad happened while opening file ",exFile);
        perror(errMessage);
    
#if (DEBUG == 1)   
    else
        fprintf(stderr,"Success opening file!!\n");
      
#endif


    setbuf(fp,inputBuffer); //set a buffer for input

    uint64_t *num = (uint64_t*) malloc(sizeof(uint64_t));
    uint64_t total = 0;
    uint64_t n = 0;

    //test for eof
    /*
       feof(*fp) - returns a boolean true if at end of file and false otherwise
     */

    while(!feof(fp))
        //fscanf returns the number of items it converted using %llu, if it's not equal to 1 we don't want to continue
            if(fscanf(fp,"%"PRIu64"",num)!=1)
                break; //you could do a lot of stuff here as far as error handling but basically something bad has happened
            total+= *num; //add to total the value at memory location num
        n++;
#if (DEBUG == 1)   
        fprintf(stderr,"line number %"PRIu64"\n",n);
#endif 
    

    free(num);

    const double average = (double) total / (double) n;
    //close the inputfile
    fclose(fp);

    //declare our outputfile, use a pipe in this case to a java process
    //we open a java process for this process to pipe to, also it is 
    //technically a bi-directional pipe so we can use any of the modifiers
    //like r/w/r+/etc
    static const char* outFile = "java -cp . StreamTest";

    FILE *fp_out = popen(outFile,"w");
    //setbuf(fp_out,outputBuffer);

    fprintf(fp_out,"Total: %"PRIu64", Integers: %"PRIu64", Average: 
            %.4f\n",total,n,average);



    /*
       int fflush(*fp) pushes any data in the buffer to be written
       the return value returns 0 if successful or !=0 if an error 
       occurs....remember return values in C often equal exceptions

     */   
    fflush(fp_out);

    /* int */
    fclose(fp_out);

    return 1;

这是制作文件

CC ?=gcc
JCC ?= javac
FLAGS ?= -Wall -O2
JFLAGS ?= -g -verbose

all: c_app StreamTest

c_app: c_app.c
    $(CC) $(FLAGS) -o c_app c_app.c

StreamTest: StreamTest.java
    $(JCC) $(JFLAGS) StreamTest.java $(LIBS)

clean:
    rm -f c_app StreamTest.class

ap.text 文件只是一堆数字

流测试

import java.io.BufferedInputStream; 
import java.io.IOException;
import java.io.InputStream;

public class StreamTest

private static final int buffer = 4096;

public static void main(String[] args) throws Exception 

    String pass=null;
    InputStream is = null;
    BufferedInputStream bis = null;
    try
    
        bis = new BufferedInputStream(System.in,buffer);
        StringBuilder sb = new StringBuilder();
        //sb.append((char)bis.read());
        while(bis.available() > 0)
            sb.append((char)bis.read());
        
        pass = sb.toString();
        System.out.println("JAVA SIDE: "+pass);
        bis.close();
    
    catch(IOException ex)
    

    

    finally
    


    
    //pass = "hi";
    mainLaptop.main(pass);

    

这是我在 StreamTest 类中调用的 mainLaptop 类。

public class mainLaptop 


public static void main(String arg) throws Exception 
   
    //Timing out? change the IP!
    String ip="192.168.137.127";
    String Pi1Q1="Leonardo";
    String Pi1Q2="Raphael";
    String Pi2Q3="Donatello";
    String Pi2Q4="Michelangelo";
    String pass=arg;

    Send.send(ip, Pi1Q1, pass);
    Send.send(ip, Pi1Q2, pass);
    Send.send(ip, Pi2Q3, pass);
    Send.send(ip, Pi2Q4, pass);

/*  Recv.recv(ip, Pi1Q1);
    Recv.recv(ip, Pi1Q2);
    Recv.recv(ip, Pi2Q3);
    Recv.recv(ip, Pi2Q4);*/


这是在我的 mainLaptop 类中调用的发送代码

import com.rabbitmq.client.Channel;     
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class Send 


  public static void send(String ip, String Q, String pass) throws 
Exception 
  

 ConnectionFactory factory = new ConnectionFactory();

//set connection info
factory.setHost(ip);
factory.setUsername("test");
factory.setPassword("test");

//create connection
Connection connection = factory.newConnection();

//create channel
Channel channel = connection.createChannel();

//publish message
   // int a = 1; 
//while (a!=0)

    channel.queueDeclare(Q, false, false, false, null);
    //for(int i=1; i<=2; i++)
    
        //String message = pass;
        channel.basicPublish("", Q, null, pass.getBytes("UTF-8"));
        System.out.println(" [x] Sent '" + pass + "'" + Q);
    

    //a--;      



//SHUT IT ALL DOWN!
channel.close();
connection.close();

  

用@EJP 建议的编辑一些更新了流测试

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;

public class StreamTest
private static final int buffer = 4096;
static String pass;
public static void main(String[] args) 

    InputStream is = null;
    BufferedInputStream bis = null;
    BufferedReader bir = null;
    try
    
        bis = new BufferedInputStream(System.in,buffer);
        StringBuilder sb = new StringBuilder();



        while ((bir.readLine()) != null) 
        
         // Do something here. Who knows
        

        /*while(bis.available() > 0)
            sb.append((char)bis.read());
        */


        /*int b; 
        while ((b = bis.read()) != -1) 
        
            // do something with 'b' 
            sb.append((char)b);

        */

        pass=sb.toString();

        System.out.println("JAVA SIDE: "+pass);
        bir.close();
        bis.close();
    
    catch(IOException ex)
    

    
    finally


    


try 
mainLaptop.main(pass);
 catch (Exception e) 
// TODO Auto-generated catch block
e.printStackTrace();




【问题讨论】:

教程质量差。 ready() 不是对流结束的测试,与 available() 一样。但它在读取循环中不包含两个 read() 调用。 如果以下答案不够,请提供minimal reproducible example。 while ((line = BufferedReader.readLine()) != null) 返回错误“无法从 BufferedReader 类型对非静态方法 readLine() 进行静态引用” 哦,来吧。 BufferedReader.readLine() 是方法的名称。您应该能够自己实例化BufferedReader 这是现在的结果。 Exception in thread "main" java.lang.NullPointerException at StreamTest.main(StreamTest.java:20 【参考方案1】:

available() 不是流结束的测试。请参阅 Javadoc。去掉它,当read()返回-1时终止读取循环,或者使用BufferedReader.readLine()当它返回null时终止。

并且不要忽略异常。

编辑为了强调这一点,您修改后的循环应为:

int b;
while ((b = bis.read()) != -1)

    sb.append((char)b);

更可能

String line;
while ((line = bufferedReader.readLine()) != null)

    // Do something with 'line', other than merely appending it to a StringBuffer

【讨论】:

以上是关于试图通过管道将 C 中生成的数据传递给 Java 类。传递变量在java中出现空白而不是有数据的主要内容,如果未能解决你的问题,请参考以下文章

如何将解析器中的数据传递给函数

如何将一个组件中查询的数据传递给另一个组件以用作查询变量?

如何在通过广播接收器将 JobIntentService 之间的数据传递给活动时防止 TransactionTooLarge 异常

当我的应用程序通过我的 UITabBar 完成启动时,如何将加载的数据传递给 UITableView?

C语言 unsigned short 如何相互转 signed char

将异步获取的数据传递给子道具