BufferedWriter.write()与BufferedReader.readLine() (附带Java中的Runtime exec)

昨天在实现一个Java程序启动执行C++程序中,遇到了一些问题,先准备把它记录下来(利人利己

准备实现的测试功能是这样的:在一个java程序中启动一个C++可执行程序,然后java程序和C++程序相互通信(java端发送消息给C++程序处理,C++处理完成后将返回一个结果消息给java程序。不断往返循环直至输入exit指令结束)。

首先,在一个java程序中启动一个C++可执行程序 使用的是java的Runtime.getRuntime().exec()Process类exec()官方说明 http://docs.oracle.com/javase/6/docs/api/java/lang/Process.html

【另外,还有一种java的JNI (Java Native Interface)框架可以实现java调用其它编程语言的方法】

*说明*:

使用exec()方式,C++程序的所有标准 io(即 stdin、stdout和
stderr)操作都将通过三个流(getOutputStream()、getInputStream()和
getErrorStream()) 重定向到父进程。

因此,使用上述重定向特性就可以通过标准输入输出实现Java与C++程序间的简单通信,在处理通信I/O时,使用了BufferedReader和BufferedWriter作为通信输入输出的缓冲,方便对消息处理。

关于readLine(),此处有篇博文点击打开链接 http://blog.csdn.net/swingline/article/details/5357581

*注意*:

1. 由于C++端是按行读取消息的,所以在Java端发送消息时要注意每个消息的结尾都必须加上换行符。这就是为何我在writeToCpp.write(wstr+"\n"); 中要+"\n"的原因。(就是因为这个换行符没加导致我调bug费了好长时间,之前一直找不出什么原因导致java端在console中输入消息发送后java程序就跑飞了。。后来发现在eclipse的console中输入字符串回车后该字符串末尾是不带换行符的。。。)


2. 下面的java代码中开辟了一个线程来处理从C++端传送来的消息打印。非常好用!

3. 【引用自点击打开链接

  • 误以为readLine()是读取到没有数据时就返回null(因为其它read方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数当没有数据读取时,就一直会阻塞在那,而不是返回null;因为readLine()阻塞后,System.out.println(message)这句根本就不会执行到,所以在接收端就不会有东西输出。要想执行到System.out.println(message),一个办法是发送完数据后就关掉流,这样readLine()结束阻塞状态,而能够得到正确的结果,但显然不能传一行就关一次数据流;另外一个办法是把System.out.println(message)放到while循环体内就可以。

另外有个问题没解决:

针对Java启动C++程序场景,如何配置使用eclipse和visual studio (2013)使得我能够从eclipse中debug Java程序跟踪到C++程序后能在Visual studio中继续能debug呢?

我查了下,好像可以通过Visual studio的attach to process功能能够实现联调(在VS中依次打开Debug -> Attach to process. 然后找到启动的java进程选中确定【我选的是javaw.exe】),但是我尝试了好久没有成功。(一开始提示找不到PDB文件,我就去vs的TOOLS -> Options -> Debugging -> Symbols勾选了“Microsoft Symbol Servers” ,部分PDB文件就可以加载了,但还有部分PDB文件加载不上。。。打的断点也是显示黄色圆圈带感叹号
【提示信息见下文】)

还请有经验的大侠能帮忙提供下eclipse与VS联调的解决方案,谢谢!!

下面就是实现了双边通信的java和C++源代码

Java端代码片段:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class JavaCallCpp {

			static BufferedWriter writeToCpp;
			static BufferedReader readFromCpp;

	public static void main(String[] args) throws IOException {

		try {
			Process execute = Runtime.getRuntime().exec("D:/WorkSpace/vs/stringstream/Debug/stringstream");
			//int exitVal = execute.waitFor();
			writeToCpp = new BufferedWriter(new OutputStreamWriter(execute.getOutputStream()));
			readFromCpp = new BufferedReader(new InputStreamReader(execute.getInputStream()));

			MyThread myThread=new MyThread(readFromCpp);
			myThread.start();
			/*Write to C++*/
			writeToCpp.write("have entered the scentence\n");
			writeToCpp.write("aaaaa\n");
			writeToCpp.flush();

			//writeToCpp.write("quit\n");
			//writeToCpp.flush();
			/*Read from C++*/
			writeToCpp.write("abcd\n");
			writeToCpp.flush();
			Scanner writer = new Scanner(System.in);
//			while(true){
			String wstr = null;

			while(true){

					wstr=writer.next();
					if(wstr.equals("exit")){
						writer.close();
						break;
					}
					System.out.println(wstr);
					writeToCpp.write(wstr+"\n");
					writeToCpp.flush();
				}
			writeToCpp.flush();
				System.out.println("out of while.");
				/*while((readLine = readFromCpp.readLine()) != null){
					System.out.println(readLine);
				}*/
//			}
			//writerString.close();
			execute.destroyForcibly();//强制终止
			execute.getInputStream().close();
			readFromCpp.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
class MyThread extends Thread{
	private BufferedReader bfr;
	public MyThread(BufferedReader bfr){
		this.bfr=bfr;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		String readLine = null;
		Boolean _b=true;
		try {
			while(_b){
				readLine=bfr.readLine();
				if(readLine==null)
				{
					_b=false;
				}else{
					System.out.println(readLine);
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

C++端程序片段:

void fun1(){
	string cmd;
	string line, word;
	cout << "enter a scentence, and exit with typing \"quit\""<<endl;
	while (getline(cin, line)&& line!="quit")
	{
		stringstream stream(line);
		cout << stream.str() << endl;
		while (stream >> word){ cout << word << endl; }
	}

	while (true){
		cout << "please input a command, and exit with typing \"exit\": "<<endl;
		getline(std::cin, cmd);
		if (0==strcmp(cmd.c_str(),"exit")){ //strcmp返回str1-str2的值
			cout << "cmd is exit, exit 0 \n";
			exit (0);
		}
		else if (strcmp(cmd.c_str(), "continue") !=0){
			cout << "cmd is not \"continue\" to break\n";
			continue;
		}
		else{
			cout << "cmd is continue, break while(true) \n";
			break;
		}
	}
	cout << "OK, pass over while(true) \n";
}

/*以下是针对debug问题的(可忽略)*/

eclipse与visual studio联调debug的提示信息

'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\bin\javaw.exe'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\ntdll.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\kernel32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\KernelBase.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\advapi32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\msvcrt.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\sechost.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\rpcrt4.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\user32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\gdi32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.10586.0_none_8c15ae12515e1c22\comctl32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\combase.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\bcryptprimitives.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\imm32.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\msvcr100.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\server\jvm.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\psapi.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\wsock32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\ws2_32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\version.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\winmm.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\winmmbase.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\cfgmgr32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\verify.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\java.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\jdwp.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\npt.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\zip.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\shell32.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\windows.storage.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\shlwapi.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\kernel.appcore.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\SHCore.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\powrprof.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\profapi.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Program Files\Java\jdk1.8.0_65\jre\bin\dt_socket.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\NapiNSP.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\pnrpnsp.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\nlaapi.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\mswsock.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\dnsapi.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\nsi.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\winrnr.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\wshbth.dll'. Symbols loaded.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\FWPUCLNT.DLL'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\bcrypt.dll'. Cannot find or open the PDB file.
'javaw.exe' (Win32): Loaded 'C:\Windows\System32\rasadhlp.dll'. Cannot find or open the PDB file.
时间: 2024-10-11 11:27:50

BufferedWriter.write()与BufferedReader.readLine() (附带Java中的Runtime exec)的相关文章

Java中使用Runtime和Process类运行外部程序

在编写Java程序时,有时候我们需要调用其他的诸如exe,shell这样的程序或脚本.在Java中提供了两种方法来启动其他程序: (1) 使用Runtime的exec()方法 (2) 使用ProcessBuilder的start()方法 Runtime和ProcessBulider提供了不同的方式来启动程序,设置启动参数.环境变量和工作目录.但是这两种方法都会返回一个用于管理操作系统进程的Process对象. 使用Runtime.getRuntime().exec()方法可以在java程序里运行

Java中的Runtime类

Runtime类描述了虚拟机一些信息.该类采用了单例设计模式,可以通过静态方法 getRuntime()获取Runtime类实例.下面演示了获取虚拟机的内存信息: 1 package Main; 2 3 public class Main 4 { 5 public static void main(String[] args) throws Exception 6 { 7 Runtime runtime = Runtime.getRuntime(); 8 System.out.println("

2.Java基础之Runtime对象

毕向东老师Java基础学习笔记——Runtime对象 今天学习Java中的Runtime对象后,感觉这个对象对我们主要有以下几点用处. 1.使用java代码打开本地可执行文件,比如打开一个计算器. 2.打开一个程序,并用该程序打开一个支持的文件. 比如:1.打开记事本,用记事本打开*.java文件, 2.打开暴风影音播放器,用播放器打开一个本地视频. 范例代码如下: /************************************** Runtime对象: 1.该类并没有提供构造函数.

java中的new BufferedReader(new InputStreamReader(System.in))

流 JAVA /IO 基本小结 通过一行常见的代码讨论:new BufferedReader(new InputStreamReader(System.in)) java的IO是基于流(stream)概念的,什么是流呢,作为初学者, 我是这样理解的,在各个应用之间传送的是BITS,这些BIT可已被认为是流体,可以就认为是水流,那么用来在各个水源之间转移水的工具应该选择什么呢?一般情况下,水管是可以的,所以数据我将数据源比作水源,将流对象比作水管 这样就有了对流的第一步认识,它再也不神秘了. 对于

10.4 缓冲流 BufferedReader &amp; BufferedWriter&amp; 缓冲流特殊功能readLine

缓冲流和正常流的使用大致相同,缓冲流效率更高. package day10_io_fileWrite_Read.buffer_stream; import java.io.*; /* * BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符.数组和字符串的高效写入. * BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符.数组和行的高效读取. */ public class BufferedStream { public static

JAVA中BufferedReader设置编码的必要性

实验环境 Myeclipse 默认编码 UTF-8 先看两种读文件的方式: 方式一: InputStreamReader fReader = new InputStreamReader(new FileInputStream(filePathString),"UTF-8"); BufferedReader reader = new BufferedReader(fReader); String line; while ((line = reader.readLine()) != nul

Java中BufferedReader和scanner的对比

Scanner 和BufferedReader同样能实现将键盘输入的数据送入程序, import java.io.*;import java.util.Scanner;public class C {public static void main(String []args) throws IOException{ String x1,x2;    int sum=0; System.out.print("BufferedReader方法\ninput two number:"); /

Java中的IO流

Java中的IO流是实现输入/输出的基础. 按照流的方向不同:分为输入流和输出流. 按照处理数据单位的不同:分为字节流(8位)和字符流(16位). 按照功能不同:分为节点流和处理流 所有面向字节的流类都继承于InputStream类(输入流) 或OutputStream类(输出流),这两个类是抽象类,我们可以利用它的子类来完成不同的功能. InputStream.OutputStream都是抽象类 InputStream抽象了应用程序读取数据的方式 OutputStream抽象类应用程序写出数据

java中常用的包、类、以及包中常用的类、方法、属性-----io包

由于最近有需要,所以下面是我整理的在开发中常用的包.类.以及包中常用的类.方法.属性:有需要的看看 java中常用的包.类.以及包中常用的类.方法.属性 常用的包 java.io.*; java.util.*; java.lang.*; java.math.*; java.sql.*; java.text.*; java.awt.*; javax.swing.*;   包名 接口 类 方法 属性 java.io.*; java.io.Serializable实现序列化 java.io.Buffe