在Java程序中截获控制台输出
Java远程调用Shell脚本并获取输出信息【推荐】
Java远程调⽤Shell脚本并获取输出信息【推荐】1、添加依赖<dependency><groupId>ch.ethz.ganymed</groupId><artifactId>ganymed-ssh2</artifactId><version>262</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>2、Api说明⾸先构造⼀个连接器,传⼊⼀个需要登陆的ip地址;Connection conn = new Connection(ipAddr);模拟登陆⽬的服务器,传⼊⽤户名和密码;boolean isAuthenticated = conn.authenticateWithPassword(userName, passWord);它会返回⼀个布尔值,true 代表成功登陆⽬的服务器,否则登陆失败。
打开⼀个session,执⾏你需要的linux 脚本命令;Session session = conn.openSession();session.execCommand(“ifconfig”);接收⽬标服务器上的控制台返回结果,读取br中的内容;InputStream stdout = new StreamGobbler(session.getStdout());BufferedReader br = new BufferedReader(new InputStreamReader(stdout));得到脚本运⾏成功与否的标志:0-成功⾮0-失败System.out.println(“ExitCode: ” + session.getExitStatus());关闭session和connectionsession.close();conn.close();Tips:通过第⼆部认证成功后当前⽬录就位于/home/username/⽬录之下,你可以指定脚本⽂件所在的绝对路径,或者通过cd导航到脚本⽂件所在的⽬录,然后传递执⾏脚本所需要的参数,完成脚本调⽤执⾏。
java截取方法
java截取方法Java截取方法,即从字符串中截取需要的一部分内容。
在Java中,我们可以使用substring()方法来截取字符串,也可以使用StringTokenizer类等其他的方法来实现。
本文将着重介绍substring()方法的使用及其注意事项。
一、substring()方法的基本格式和作用Java中字符串的截取方法是通过String类提供的substring()方法来实现的,它的基本格式如下:``` public String substring(int beginIndex) public String substring(int beginIndex, int endIndex) ```其中,第一个参数代表要截取的子串的起始位置,第二个参数代表要截取的子串的结束位置。
注意,substring()方法截取出的字符串不包括指定的结束位置所在的字符,即该字符不在截取出的字符串中。
这个方法的作用是从目标字符串中截取出指定位置的子串,并返回一个新的字符串。
二、substring()方法的使用实例下面通过几个例子来演示substring()方法的使用。
例1. 截取字符串中前面的几个字符``` public class TestSubstring { public static void main(String[] args) { String str = "Hello, world!"; String newStr = str.substring(0, 5);System.out.println(newStr); } }输出结果:Hello ```在这个程序中,我们截取了字符串“Hello, world!”的前5个字符,最终输出的结果是“Hello”。
例2. 截取字符串中的一段子串``` public class TestSubstring { public static void main(String[] args) { String str = "Hello, world!"; String newStr = str.substring(7, 12);System.out.println(newStr); } }输出结果:world ```在这个程序中,我们截取了字符串“Hello, world!”中从第8个字符开始,到第12个字符(不包括第12个字符)的子串“world”,最终输出的结果就是这个子串。
java编程实现屏幕截图(截屏)代码总结
java编程实现屏幕截图(截屏)代码总结本⽂实例总结了常见的java编程实现屏幕截图⽅法。
分享给⼤家供⼤家参考,具体如下:⽅法⼀:import java.awt.Desktop;import java.awt.Dimension;import java.awt.Rectangle;import java.awt.Robot;import java.awt.Toolkit;import java.awt.image.BufferedImage;import java.io.File;import javax.imageio.ImageIO;public class CaptureScreen {public static void captureScreen(String fileName, String folder) throws Exception {Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();Rectangle screenRectangle = new Rectangle(screenSize);Robot robot = new Robot();BufferedImage image = robot.createScreenCapture(screenRectangle);//保存路径File screenFile = new File(fileName);if (!screenFile.exists()) {screenFile.mkdir();}File f = new File(screenFile, folder);ImageIO.write(image, "png", f);//⾃动打开if (Desktop.isDesktopSupported()&& Desktop.getDesktop().isSupported(Desktop.Action.OPEN))Desktop.getDesktop().open(f);}public static void main(String[] args) {try {captureScreen("e:\\你好","11.png");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}⽅法⼆:package com.qiu.util;import java.io.*;import javax.swing.*;import java.awt.*;import java.awt.event.*;import java.awt.image.*;import javax.imageio.*;/*** ⼀个简单的屏幕抓图***/public class ScreenCapture {// test mainpublic static void main(String[] args) throws Exception {String userdir = System.getProperty("user.dir");File tempFile = new File("d:", "temp.png");ScreenCapture capture = ScreenCapture.getInstance();capture.captureImage();JFrame frame = new JFrame();JPanel panel = new JPanel();panel.setLayout(new BorderLayout());JLabel imagebox = new JLabel();panel.add(BorderLayout.CENTER, imagebox);imagebox.setIcon(capture.getPickedIcon());capture.saveToFile(tempFile);capture.captureImage();imagebox.setIcon(capture.getPickedIcon());frame.setContentPane(panel);frame.setSize(400, 300);frame.show();System.out.println("Over");}private ScreenCapture() {try {robot = new Robot();} catch (AWTException e) {System.err.println("Internal Error: " + e);e.printStackTrace();}JPanel cp = (JPanel) dialog.getContentPane();cp.setLayout(new BorderLayout());labFullScreenImage.addMouseListener(new MouseAdapter() {public void mouseReleased(MouseEvent evn) {isFirstPoint = true;pickedImage = fullScreenImage.getSubimage(recX, recY, recW,recH);dialog.setVisible(false);}});labFullScreenImage.addMouseMotionListener(new MouseMotionAdapter() {public void mouseDragged(MouseEvent evn) {if (isFirstPoint) {x1 = evn.getX();y1 = evn.getY();isFirstPoint = false;} else {x2 = evn.getX();y2 = evn.getY();int maxX = Math.max(x1, x2);int maxY = Math.max(y1, y2);int minX = Math.min(x1, x2);int minY = Math.min(y1, y2);recX = minX;recY = minY;recW = maxX - minX;recH = maxY - minY;labFullScreenImage.drawRectangle(recX, recY, recW, recH);}}public void mouseMoved(MouseEvent e) {labFullScreenImage.drawCross(e.getX(), e.getY());}});cp.add(BorderLayout.CENTER, labFullScreenImage);dialog.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); dialog.setAlwaysOnTop(true);dialog.setMaximumSize(Toolkit.getDefaultToolkit().getScreenSize());dialog.setUndecorated(true);dialog.setSize(dialog.getMaximumSize());dialog.setModal(true);}// Singleton Patternpublic static ScreenCapture getInstance() {return defaultCapturer;}/** 捕捉全屏慕 */public Icon captureFullScreen() {fullScreenImage = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));ImageIcon icon = new ImageIcon(fullScreenImage);return icon;}/** 捕捉屏幕的⼀个矫形区域 */public void captureImage() {fullScreenImage = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));ImageIcon icon = new ImageIcon(fullScreenImage);labFullScreenImage.setIcon(icon);dialog.setVisible(true);}/** 得到捕捉后的BufferedImage */public BufferedImage getPickedImage() {return pickedImage;}/** 得到捕捉后的Icon */public ImageIcon getPickedIcon() {return new ImageIcon(getPickedImage());}/*** 储存为⼀个⽂件,为PNG格式** @deprecated replaced by saveAsPNG(File file)**/@Deprecatedpublic void saveToFile(File file) throws IOException {ImageIO.write(getPickedImage(), defaultImageFormater, file);}/** 储存为⼀个⽂件,为PNG格式 */public void saveAsPNG(File file) throws IOException {ImageIO.write(getPickedImage(), "png", file);}/** 储存为⼀个JPEG格式图像⽂件 */public void saveAsJPEG(File file) throws IOException {ImageIO.write(getPickedImage(), "JPEG", file);}/** 写⼊⼀个OutputStream */public void write(OutputStream out) throws IOException {ImageIO.write(getPickedImage(), defaultImageFormater, out);}// singleton design patternprivate static ScreenCapture defaultCapturer = new ScreenCapture();private int x1, y1, x2, y2;private int recX, recY, recH, recW; // 截取的图像private boolean isFirstPoint = true;private BackgroundImage labFullScreenImage = new BackgroundImage();private Robot robot;private BufferedImage fullScreenImage;private BufferedImage pickedImage;private String defaultImageFormater = "png";private JDialog dialog = new JDialog();}/** 显⽰图⽚的Label */class BackgroundImage extends JLabel {public void paintComponent(Graphics g) {super.paintComponent(g);g.drawRect(x, y, w, h);String area = Integer.toString(w) + " * " + Integer.toString(h);g.drawString(area, x + (int) w / 2 - 15, y + (int) h / 2);g.drawLine(lineX, 0, lineX, getHeight());g.drawLine(0, lineY, getWidth(), lineY);}public void drawRectangle(int x, int y, int width, int height) {this.x = x;this.y = y;h = height;w = width;repaint();}public void drawCross(int x, int y) {lineX = x;lineY = y;repaint();}int lineX, lineY;int x, y, h, w;}⽅法三:因为有最⼩化到系统托盘,还是需要⼀张名为bg.gif作为托盘图标,图⽚应放在同级⽬录下,否则会空指针异常。
java捕获和抛出异常
java捕获和抛出异常java 捕获和抛出异常异常通常是程序运⾏时出现的问题和错误。
如:客户输⼊数据的格式,读取的⽂件是否存在,⽹络是否保持通畅等。
java程序在执⾏过程中发⽣的异常事件分为:异常和错误异常:(Exception)异常指程序运⾏过程中出现的⾮正常现象。
可能遇到的轻微错误,可以写代码处理异常并继续继承执⾏,不应让程序中断。
错误:(Error)错误事件的发⽣通常会阻⽌程序正常运⾏。
对于java虚拟机⽆法解决的严重问题,如jvm系统内部错误,资源耗尽等情况,⼀般不编写针对性的代码进⾏处理。
对于被认为是不能恢复的严重错误,不应该抛出,⽽应该让程序中断。
错误与异常最⼤的区别是错误往往⽐异常严重,发⽣了错误,⼀般不能在应⽤程序中捕获处理,程序只能⾮正常终⽌运⾏。
异常的简单分类:(1):检查性异常最具有代表性的是⽤户错误或者是问题引起的⽽异常,这是程序员⽆法预见的。
例如要打开⼀个不存在的⽂件时,异常就发⽣了,这些异常在编译时不能被简单的忽略。
(2):运⾏时异常它是可能被程序员避免的异常,与检查性异常相反,运⾏时可以在编译时被忽略。
(3):错误错误不是异常,⽽是脱离程序员控制的问题,错误在代码中通常被忽略。
例如当栈溢出时,⼀个错误就发⽣了,他们在编译中也查不到。
java把异常当做对象来处理,并定义⼀个基类ng.Throwable作为所有异常的超类。
java异常层次结构图如下:异常处理机制(捕获)抛出异常:当出现异常事件时,系统会⾃动产⽣⼀个异常对象,然后将其传递给java运⾏时系统。
这个异常产⽣和提交的过程称为抛出异常。
捕获异常:当java运⾏时系统得到异常对象以后,它将寻找处理这⼀异常的⽅法,找到之后,运⾏时系统把当前异常对象交给该⽅法进⾏处理。
这⼀过程称为捕获。
异常处理的⼀般步骤为:异常抛出---->异常捕获---->异常处理java异常机制主要依赖于try,catch,finally,throws,throw五个关键字。
在Java程序中截获控制台输出
在程序中截获控制台输出在开发中,控制台输出仍是一个重要的工具,但默认的控制台输出有着各种各样的局限。
本文介绍如何用管道流截取控制台输出,分析管道流应用中应该注意的问题,提供了截取程序和非程序控制台输出的实例。
即使在图形用户界面占统治地位的今天,控制台输出仍旧在程序中占有重要地位。
控制台不仅是程序默认的堆栈跟踪和错误信息输出窗口,而且还是一种实用的调试工具(特别是对习惯于使用()的人来说)。
然而,控制台窗口有着许多局限。
例如在平台上,控制台只能容纳行输出。
如果程序一次性向控制台输出大量内容,要查看这些内容就很困难了。
对于使用这个启动程序的开发者来说,控制台窗口尤其宝贵。
因为用启动程序时,根本不会有控制台窗口出现。
如果程序遇到了问题并抛出异常,根本无法查看运行时环境写入到或的调用堆栈跟踪信息。
为了捕获堆栈信息,一些人采取了用()块封装()的方式,但这种方式不一定总是有效,在运行时的某些时刻,一些描述性错误信息会在抛出异常之前被写入和;除非能够监测这两个控制台流,否则这些信息就无法看到。
因此,有些时候检查运行时环境(或第三方程序)写入到控制台流的数据并采取合适的操作是十分必要的。
本文讨论的主题之一就是创建这样一个输入流,从这个输入流中可以读入以前写入控制台流(或任何其他程序的输出流)的数据。
我们可以想象写入到输出流的数据立即以输入的形式“回流”到了程序。
本文的目标是设计一个基于的文本窗口显示控制台输出。
在此期间,我们还将讨论一些和管道流(和)有关的重要注意事项。
图一显示了用来截取和显示控制台文本输出的程序,用户界面的核心是一个。
最后,我们还要创建一个能够捕获和显示其他程序(可以是非的程序)控制台输出的简单程序。
一、管道流要在文本框中显示控制台输出,我们必须用某种方法“截取”控制台流。
换句话说,我们要有一种高效地读取写入到和所有内容的方法。
如果你熟悉的管道流和,就会相信我们已经拥有最有效的工具。
写入到输出流的数据可以从对应的输入流读取。
java 字符串截取方法
java 字符串截取方法Java 字符串截取方法在Java编程中,经常会遇到需要截取字符串的情况。
字符串截取是指从一个字符串中获取部分内容的操作,常用于处理字符串的长度、格式等需求。
本文将介绍Java中常用的字符串截取方法,并提供使用示例。
1. 使用substring()方法截取字符串Java中的String类提供了substring()方法,可以用于截取字符串的指定部分。
substring()方法有两种重载形式,一种是指定截取起始位置的方式,另一种是同时指定起始位置和结束位置的方式。
1.1 使用起始位置截取字符串substring(int beginIndex)方法可以从指定起始位置开始截取字符串,包括起始位置的字符。
例如:```javaString str = "Hello World";String result = str.substring(6);System.out.println(result); // 输出 "World"```上述代码中,str.substring(6)表示从索引为6的字符开始截取,截取的结果是"World"。
1.2 使用起始位置和结束位置截取字符串substring(int beginIndex, int endIndex)方法可以从指定起始位置开始截取字符串,并指定截取的结束位置,不包括结束位置的字符。
例如:```javaString str = "Hello World";String result = str.substring(6, 11);System.out.println(result); // 输出 "World"```上述代码中,str.substring(6, 11)表示从索引为6的字符开始截取,截取到索引为10的字符,截取的结果是"World"。
java控制台输入输出
java控制台输⼊输出⼀、⽐较传统的输⼊⽅法⽤输⼊流,得到字符串后要另⾏判断、转换案例import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class MainRun {public static void main(String[] args) {try {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输⼊⼀个整数:");String str1 = bufferedReader.readLine();Integer int1 = Integer.valueOf(str1);System.out.println("输⼊的整数是:" + int1);System.out.println("请输⼊⼀个浮点数:");String str2 = bufferedReader.readLine();Double double1 = Double.valueOf(str2);System.out.println("输⼊的浮点数是:" + double1);} catch (IOException e) {e.printStackTrace();}}}请输⼊⼀个整数:234输⼊的整数是:234请输⼊⼀个浮点数:23输⼊的浮点数是:23.0⼆、JDK5以后有了Scanner处理控制台输⼊格式1: Scanner sc = new Scanner(new BufferedInputStream(System.in));格式2: Scanner sc = new Scanner(System.in);在有多⾏数据输⼊的情况下,⼀般这样处理:while(sc.hasNextInt()){...} 或者while(sc.hasNext()){}读⼊⼀个字符串: String str = sc.next();读⼊⼀整⾏数据: String lineString=sc.nextLine();读⼊⼀个布尔值:boolean boolenaNumber = sc.nextBoolean();读⼊⼀个字节型数据:byte byteNumbe = sc.nextByte();读⼊⼀个短整型数据:short shortNumber=sc.nextShort();读⼊⼀个整数:int intNumber = sc.nextInt();读⼊⼀个长整型数据:long longNumber=sc.nextLong();读⼊⼀个单精度浮点数:float floatNumber=sc.nextFloat();读⼊⼀个双精度浮点数:double doubleNumber=sc.nextDouble();对于计算代码运⾏时间:long startTime = System.nanoTime();// … the code being measured …long estimatedTime = System.nanoTime() - startTime;输⼊案例:输⼊数据有多组,每组占2⾏,第⼀⾏为⼀个整数N,指⽰第⼆⾏包含N个实数Scanner sc = new Scanner(System.in);while(sc.hasNext()){int n = sc.nextInt();for(int i=0;i<n;i++){double a=sc.nextDouble();...}三、输出:输出内容:System.out.print("");输出内容并换⾏:System.out.println("");格式化输出: System.out.format(String format, Object ... args);等价于 System.out.printf((String format, Object ... args);各种格式化样式说明:格式化输出案例:// System.out.printf(format, args);format为指定的输出格式,args参数System.out.printf("%+8.3f\n", 3.14); // "+"表⽰后⾯输出的数字会有正负号,正的+,负的-// ;8.3f表⽰输出浮点数,宽度为8,⼩数点保持3位有效System.out.printf("%+-8.3f\n", 3.14);// "-"表⽰靠左对齐System.out.printf("%08.3f\n", 3.14);// "0"8位宽度中⾃动补0System.out.printf("%(8.3f\n", -3.14);// "("如果是负数,⾃动加上( )System.out.printf("%,f\n", 123456.78); // ","⾦钱表⽰⽅法,每三位有⼀个逗号System.out.printf("%x\n", 0x2a3b); // 输出16进制数System.out.printf("%#x\n", 0x2a3b);// 输出带0x标识的16进制数System.out.printf("⽼板:您名字%s,年龄:%3d岁,⼯资:%,-7.2f\n", "ajioy", 21,36000.00);System.out.printf("⽼板:您名字%1$s,年龄:%2$#x岁\n", "ajioy", 38); // "n{1}quot;表⽰⽤第n个参数输出结果:+3.140+3.1400003.140(3.140)123,456.7800002a3b0x2a3b⽼板:您名字ajioy,年龄: 21岁,⼯资:36,000.00⽼板:您名字ajioy,年龄:0x26岁五、规格化输出SimpleDateFormat:SimpleSimpleDateFormat myFmt = new SimpleDateFormat("yyyy年MM⽉dd⽇ HH时mm分ss秒 E ");System.out.println(myFmt.format(new Date()));输出结果:2016年09⽉08⽇ 17时34分01秒星期四DecimalFormat:DecimalFormat 是 NumberFormat 的⼀个具体⼦类,⽤于格式化⼗进制数字。
JAVA输入输出流和文件操作
JAVA输入输出流和文件操作
1、JAVA输入输出流
Java的输入/输出流机制是Java中最基本的控制机制,它是把Java 程序和外部文件和网络服务之间建立的数据传输通道,是Java程序访问来自外部资源的基本手段。
Java的输入/输出流机制是Java中最基本的控制机制,它是把Java 程序和外部文件和网络服务之间建立的数据传输通道,是Java程序访问来自外部资源的基本手段。
Java的输入/输出流机制是将不同的数据源统一到同一结构,从而使Java程序与各种外部资源(文件、网络服务)之间可以进行输入/输出操作。
普通的Java程序可以使用这些IO流来读取和写入文件,从而实现文件的操作。
Java的输入/输出流系统分为字节流和字符流两种。
字节流是用来处理二进制数据流的,可以用来处理原始数据流;而字符流是用来处理字符流的,可以用来处理文本文件。
2、JAVA文件操作
文件是操作系统中用来存储信息的基本单位,在JAVA编程中,我们使用File来操作文件,File类是java.io包中的类,它是为了访问底层操作系统提供的文件和目录的操作方法。
File类可以用来操作一些文件系统相关的信息,比如:文件名、文件大小、文件是否存在等等,我们可以使用File类来实现文件的创建、删除、复制、移动等操作。
另外,如果要实现文件的读写操作。
Java输入输出详解零基础学Java
Java输入输出详解零基础学Java本篇主要介绍Java的输入与输出,当然,这里说的是控制台下的输入与输出,窗口程序的设计将会再后续篇章中有详细说明。
Java的输出很简单,调用System.out.println(即可打印输出你想要输出的内容。
我们之前也已经看到过。
调用println(方法时,会自动在后面加上换行符,如果不希望它加换行符的话,就要使用print(方法了,之后的打印输出会紧跟其后,而不是另起一行。
另外,还有一个很常用的方法,那就是printf(,学过C或者C++的话,对这个printf(应该很熟悉,没错,在Java里几乎是一模一样的。
可以用来格式化输出内容。
第一个参数代表格式,格式中会有一个或者多个转换符,后续参数代表替换内容,用于替换转换符。
说这么多也没用,直接上代码。
package pers.frank.test;import java.util.Date;public class Testpublic static void main(String[] args)/*** 输出字符串 ***/// %s表示输出字符串,也就是将后面的字符串替换模式中的%sSystem.out.printf("%s", new Integer(1212));// %n表示换行System.out.printf("%s%n", "end line");// 还可以支持多个参数System.out.printf("%s = %s%n", "Name", "Zhangsan");// %S将字符串以大写形式输出System.out.printf("%S = %s%n", "Name", "Zhangsan");// 支持多个参数时,可以在%s之间插入变量编号,1$表示第一个字符串,3$表示第3个字符串System.out.printf("%1$s = %3$s %2$s%n", "Name", "san", "Zhang");/*** 输出boolean类型 ***/System.out.printf("true = %b; false = ", true);System.out.printf("%b%n", false);/*** 输出整数类型***/Integer iObj = 342;// %d表示将整数格式化为10进制整数System.out.printf("%d; %d; %d%n", -500, 2343L, iObj);// %o表示将整数格式化为8进制整数System.out.printf("%o; %o; %o%n", -500, 2343L, iObj);// %x表示将整数格式化为16进制整数System.out.printf("%x; %x; %x%n", -500, 2343L, iObj);// %X表示将整数格式化为16进制整数,并且字母变成大写形式System.out.printf("%X; %X; %X%n", -500, 2343L, iObj);/*** 输出浮点类型***/Double dObj = 45.6d;// %e表示以科学技术法输出浮点数System.out.printf("%e; %e; %e%n", -756.403f, 7464.232641d, dObj); // %E表示以科学技术法输出浮点数,并且为大写形式System.out.printf("%E; %E; %E%n", -756.403f, 7464.232641d, dObj); // %f表示以十进制格式化输出浮点数System.out.printf("%f; %f; %f%n", -756.403f, 7464.232641d, dObj);// 还可以限制小数点后的位数System.out.printf("%.1f; %.3f; %f%n", -756.403f, 7464.232641d, dObj); /*** 输出日期类型***/// %t表示格式化日期时间类型,%T是时间日期的大写形式,在%t 之后用特定的字母表示不同的输出格式Date date = new Date(;long dataL = date.getTime(;// 格式化年月日// %t之后用y表示输出日期的年份(2位数的年,如99)// %t之后用m表示输出日期的月份,%t之后用d表示输出日期的日号System.out.printf("%1$ty-%1$tm-%1$td; %2$ty-%2$tm-%2$td%n", date, dataL);// %t之后用Y表示输出日期的年份(4位数的年)// %t之后用B表示输出日期的月份的完整名, %t之后用b表示输出日期的月份的简称System.out.printf("%1$tY-%1$tB-%1$td; %2$tY-%2$tb-%2$td%n", date, dataL);// 以下是常见的日期组合// %t之后用D表示以 "%tm/%td/%ty"格式化日期System.out.printf("%1$tD%n", date);//%t之后用F表示以"%tY-%tm-%td"格式化日期System.out.printf("%1$tF%n", date);/*** 输出时间类型***/// 输出时分秒// %t之后用H表示输出时间的时(24进制),%t之后用I表示输出时间的时(12进制)// %t之后用M表示输出时间的分,%t之后用S表示输出时间的秒 System.out.printf("%1$tH:%1$tM:%1$tS; %2$tI:%2$tM:%2$tS%n",date, dataL);// %t之后用L表示输出时间的秒中的毫秒System.out.printf("%1$tH:%1$tM:%1$tS %1$tL%n", date);// %t之后p表示输出时间的上午或下午信息System.out.printf("%1$tH:%1$tM:%1$tS %1$tL %1$tp%n", date); // 以下是常见的时间组合// %t之后用R表示以"%tH:%tM"格式化时间System.out.printf("%1$tR%n", date);// %t之后用T表示以"%tH:%tM:%tS"格式化时间System.out.printf("%1$tT%n", date);// %t之后用r表示以"%tI:%tM:%tS %Tp"格式化时间System.out.printf("%1$tr%n", date);/*** 输出星期***/// %t之后用A表示得到星期几的全称System.out.printf("%1$tF %1$tA%n", date);// %t之后用a表示得到星期几的简称System.out.printf("%1$tF %1$ta%n", date);// 输出时间日期的完整信息System.out.printf("%1$tc%n", date);}}这里包括了大部分的输出格式,多码几次的话就会使用了。
java print方法
Java Print 方法Java 中的 Print 方法是 Java 编程语言中打印输出的基本方法,可用于将文本或图形输出到控制台或打印机中。
本文介绍了 Java 中 Print 方法的基本概念和使用方法。
下面是本店铺为大家精心编写的5篇《Java Print 方法》,供大家借鉴与参考,希望对大家有所帮助。
《Java Print 方法》篇1Java 是一种广泛使用的编程语言,其标准库中提供了许多用于输入和输出的基本方法。
其中,Print 方法是 Java 中用于打印输出的基本方法之一。
Java 中的 Print 方法可用于将文本或图形输出到控制台或打印机中。
该方法有多个重载版本,可以接受不同类型的参数。
其中,最常用的重载版本是 Print 方法 (String),它接受一个字符串参数并打印该字符串。
下面是一个简单的示例代码,演示如何使用 Print 方法在控制台上打印输出一条消息:```public class Example {public static void main(String[] args) {System.out.println("Hello, World!");}```在上面的代码中,我们使用 System.out.println() 方法打印了一条消息 "Hello, World!"。
println() 方法是 Print 方法的一种常用形式,它将在控制台上打印一行文本。
除了使用 println() 方法外,还可以使用其他形式的 Print 方法来打印不同的内容。
例如,使用 printf() 方法可以格式化输出文本,如下所示:```public class Example {public static void main(String[] args) {System.out.printf("The answer is %d%n", 42);}}```在上面的代码中,我们使用 printf() 方法打印了一个格式化的字符串 "The answer is 42",其中 %d 表示一个整数,并被替换为参数 42。
JAVA 获得控制台的输出信息
private void initiateXXXMap(){try {// GET THE .CLASS FILE IN YOU SRC FOLDER, THE XXX.CLASS IN IT’S FOLDERClass cls = Class.forName("XXXX");// GET THE MAIN METHOD OF .CLASS FILEMethod mainMethod = cls.getDeclaredMethod("main",new Class[]{String[].class});// SET THE ARG LIST FOR MAIN METHODObject[] argListForInvokedMain = new Object[1];// INSTANCE THE ARG LIST TO STRING ARRAY [2]argListForInvokedMain[0] = new String[2];int num = 0;if(caseModel.getPropertyType().contains("Long Row")){num = 4;}else{num = 6;}String headWords = caseModel.getBeginCharacter().toUpperCase();// SET STRING[] WITH ARGS ABOVE, USED FOR ARG LISTString argsToinvoked[]={headWords ,String.valueOf(num)};// SET THE ARG LIST WITH VALUE SET ABOVEargListForInvokedMain[0]= argsToinvoked;/***To get the Info.out put to console* 1.Get the old system output* 2.Instance new system output* 3.set new System.out* 4.Call Class method to output the useful output*The output info will input to new System.out* 5.Set back system.output back***/// GET THE OLD SYSTE.OUT.PRINTPrintStream oldPrintStream = System.out;// INSTANCE NEW OUTPUTByteArrayOutputStream bos = new ByteArrayOutputStream();// SET NEW SYSTEM OUT PUTSystem.setOut(new PrintStream(bos));//CALL THE MAIN() METHOD IN XXX.CLASS FILE. IT OUT PUT XXXS TO NEW OUTPUTmainMethod.invoke(null, argListForInvokedMain);// CHANGE BACK SYSTEM OUTPUTSystem.setOut(oldPrintStream);// GET THE NEW OUT CONTENT THAT SHOULD BE IN CONSOLE IN OLD SYSTEM OUTPUTBufferedReader br = new BufferedReader(new StringReader(bos.toString()));String tmp = null;int number = 1;while ((tmp = br.readLine()) != null ){String key = "XXX" + number++;XXXMap.put(key, tmp.trim());}}catch(Exception e) {e.printStackTrace();}}。
java 切面获取control方法名
主题:Java 切面获取controller方法名内容:1. 介绍Java切面Java切面是一种AOP(Aspect-Oriented Programming)的编程范式,通过在程序运行期间动态地将代码切入到不同的方法中,实现功能模块的解耦和复用。
在Spring框架中,切面可以通过自定义注解和切点来实现对不同方法的拦截和处理。
2. 切面获取controller方法名的需求在实际的开发中,有时候我们需要在切面中获取被拦截的controller 方法的方法名,以便进行日志记录、性能监控等操作。
但是在Spring 框架中,获取controller方法名并不是一件直接的事情,需要通过一些技巧和方法来实现。
3. 使用Pointcut注解定义切点在切面中,可以通过Pointcut注解来定义切点,而切点中可以使用execution表达式来匹配不同的方法。
通过定义切点,我们可以将不同的controller方法聚合在一起,方便统一处理。
4. 通过JoinPoint获取方法名在切面的通知方法中,可以通过JoinPoint参数来获取被拦截的方法的相关信息,包括方法名、参数等。
通过JoinPoint的getSignature()方法可以获取到方法的签名,再通过getDeclaringType()方法可以获取到声明该方法的类的类型,最终通过getMethodName()方法可以获取到方法名。
5. 示例代码演示下面是一个简单的示例代码,演示了如何在切面中获取controller 方法的方法名:```javaAspectComponentpublic class LogAspect {Pointcut("execution(*.example.controller.*.*(..))")public void controllerLogPointcut() {}Before("controllerLogPointcut()")public void before(JoinPoint joinPoint) {String methodName =joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();System.out.println("调用方法:" + methodName);}}```6. 注意事项和建议在实际应用中,需要注意切面的通知方法中的参数类型和顺序,确保能正确获取到被拦截方法的相关信息。
java 截断字符串方法 -回复
java 截断字符串方法-回复Java截断字符串方法在Java编程中,经常会遇到需要截断字符串的情况。
截断字符串是指从一个较长的字符串中选取部分字符,并将其作为一个新的字符串使用。
Java提供了多种方法来完成这个任务,本文将详细介绍这些方法的使用步骤。
截断字符串的方法:1. 使用substring方法:Java的String类提供了substring方法,通过指定起始索引和结束索引,可以从原始字符串中截取部分字符。
具体用法如下:javaString originalStr = "This is a sample string.";String truncatedStr = originalStr.substring(5, 10);System.out.println(truncatedStr); 输出:is asubstring方法接受两个参数,分别是起始索引(包括)和结束索引(不包括)。
在上述示例中,起始索引为5,结束索引为10,截取了原始字符串中的第6个字符到第11个字符之间的内容,得到了结果"is a"。
可以发现,截取的范围是左闭右开的。
注意事项:- 传入的索引必须在字符串的有效范围内,否则会抛出IndexOutOfBoundsException异常。
- 若省略结束索引,则会截取从起始索引到字符串末尾的内容。
2. 使用substring方法截取从指定位置到字符串末尾的内容:如果不知道字符串的长度,只需要截取从指定位置到字符串末尾的内容,可以使用substring方法的单参数版本。
该方法只需传入起始索引,如下所示:javaString originalStr = "This is a sample string.";String truncatedStr = originalStr.substring(8);System.out.println(truncatedStr); 输出:a sample string.在上述示例中,截取了原始字符串从第9个字符(起始索引为8)到末尾的内容,得到了结果"a sample string."。
在Java程序中截获控制台输出
在Java程序中截获控制台输出在Java开发中,控制台输出仍是一个重要的工具,但默认的控制台输出有着各种各样的局限。
本文介绍如何用Java管道流截取控制台输出,分析管道流应用中应该注意的问题,提供了截取Java程序和非Java 程序控制台输出的实例。
即使在图形用户界面占统治地位的今天,控制台输出仍旧在Java程序中占有重要地位。
控制台不仅是Java程序默认的堆栈跟踪和错误信息输出窗口,而且还是一种实用的调试工具(特别是对习惯于使用println()的人来说)。
然而,控制台窗口有着许多局限。
例如在Windows 9x平台上,DOS控制台只能容纳50行输出。
如果Java程序一次性向控制台输出大量内容,要查看这些内容就很困难了。
对于使用javaw这个启动程序的开发者来说,控制台窗口尤其宝贵。
因为用javaw启动java程序时,根本不会有控制台窗口出现。
如果程序遇到了问题并抛出异常,根本无法查看Java运行时环境写入到System.out或System.err的调用堆栈跟踪信息。
为了捕获堆栈信息,一些人采取了用 try/catch()块封装main()的方式,但这种方式不一定总是有效,在Java运行时的某些时刻,一些描述性错误信息会在抛出异常之前被写入 System.out和System.err;除非能够监测这两个控制台流,否则这些信息就无法看到。
因此,有些时候检查Java运行时环境(或第三方程序)写入到控制台流的数据并采取合适的操作是十分必要的。
本文讨论的主题之一就是创建这样一个输入流,从这个输入流中可以读入以前写入Java控制台流(或任何其他程序的输出流)的数据。
我们可以想象写入到输出流的数据立即以输入的形式“回流”到了 Java程序。
本文的目标是设计一个基于Swing的文本窗口显示控制台输出。
在此期间,我们还将讨论一些和Java 管道流(PipedInputStream和 PipedOutputStream)有关的重要注意事项。
Java简单实现调用命令行并获取执行结果示例
String commandStr = "ping "; //Str"; Command.exeCmd(commandStr); } }
运行结果:
import java.io.BufferedReader; import java.io.InputStreamReader; public class Command {
public static void exeCmd(String commandStr) { BufferedReader br = null; try { Process p = Runtime.getRuntime().exec(commandStr); br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line = null; StringBuilder sb = new StringBuilder(); while ((line = br.readLine()) != null) { sb.append(line + "\n"); } System.out.println(sb.toString()); } catch (Exception e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (Exception e) { e.printStackTrace(); } } }
这篇文章主要介绍了java运行时数据区概述文中通过示例代码介绍的非常详细对大家的学习或者工作具有一定的参考学习价值需要的朋友们下面随着小编来一起学习学习吧
JAVA中文字符编码问题详解 控制台输出
JAVA中文字符编码问题详解控制台输出JAVA的中文字符乱码问题一直很让人头疼。
特别是在WEB应用中。
网上的分析文章和解决方案都很多,但总是针对某些特定情况的。
很多次遇到乱码问题后,经过极为辛苦的调试和搜索资料后终于解决,满以为自己已经掌握了对付这些字符乱码怪兽的诀窍。
可当过段时间,换了个应用或换了个环境,又会碰到那讨厌的火星文,并再次无所适从。
于是下决心好好整理一下中文字符编码问题,以方便自己记忆,也为其他程序员兄弟们提供一份参考。
首先要了解JAVA处理字符的塬理。
JAVA使用UNICODE来存储字符数据,处理字符时通常有叁个步骤:- 按指定的字符编码形式,从源输入流中读取字符数据- 以UNICODE编码形式将字符数据存储在内存中- 按指定的字符编码形式,将字符数据编码并写入目的输出流中。
所以JAVA处理字符时总是经过了两次编码转换,一次是从指定编码转换为UNICODE编码,一次是从UNICODE编码转换为指定编码。
如果在读入时用错误的形式解码字符,则内存存储的是错误的UNICODE字符。
而从最初文件中读出的字符数据,到最终在屏幕终端显示这些字符,期间经过了应用程序的多次转换。
如果中间某次字符处理,用错误的编码方式解码了从输入流读取的字符数据,或用错误的编码方式将字符写入输出流,则下一个字符数据的接收者就会编解码出错,从而导致最终显示乱码。
这一点,是我们分析字符编码问题以及解决问题的指导思想。
好,现在我们开始一只只的解决这些乱码怪兽。
一、在JAVA文件中硬编码中文字符,在eclipse中运行,控制台输出了乱码。
例如,我们在JAVA文件中写入以下代码:String text = “大家好”;System.out.println(text);如果我们是在eclipse里编译运行,可能看到的结果是类似这样的乱码:????。
那么,这是为什么呢?我们先来看看整个字符的转换过程。
1. 在eclipse窗口中输入中文字符,并保存成UTF-8的JAVA文件。
JAVA控制台命令详解
(一)命令概览javac:Java编译器,将Java源代码换成字节代java:Java解释器,直接从类文件执行Java应用程序代码appletviewer(小程序浏览器):一种执行HTML文件上的Java小程序类的Java浏览器javadoc:根据Java源代码及其说明语句生成的HTML文档jdb:Java调试器,可以逐行地执行程序、设置断点和检查变量javah:产生可以调用Java过程的C过程,或建立能被Java程序调用的C过程的头文件Javap:Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义jar:多用途的存档及压缩工具,是个java应用程序,可将多个文件合并为单个JAR归档文件。
htmlConverter——命令转换工具。
native2ascii——将含有不是Unicode或Latinl字符的的文件转换为Unicode编码字符的文件。
serialver——返回serialverUID。
语法:serialver[show]命令选项show是用来显示一个简单的界面。
输入完整的类名按Enter键或"显示"按钮,可显示serialverUID。
(二)命令详细介绍补充详细:1.javac.exe用法:javac<选项><源文件>可能的选项包括:-g生成所有调试信息-g:none生成无调试信息-g:{lines,vars,source}生成只有部分调试信息-O优化;可能妨碍调试或者增大类文件-nowarn生成无警告-verbose输出关于编译器正在做的信息-deprecation输出使用了不鼓励使用的API的源程序位置-classpath<路径>指定用户类文件的位置-sourcepath<路径>指定输入源文件的位置-bootclasspath<路径>覆盖自举类文件的位置-extdirs<目录(多个)>覆盖安装的扩展类的位置-d<目录>指定输出类文件的位置-encoding<编码>指定源文件中所用的字符集编码-target<版本>生成指定虚拟机版本的类文件-help Print a synopsis of standard options2.Java.exeJava在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOME\bin\java–option来启动,-option为虚拟机参数,JAVA_HOME为JDK安装路径,通过这些参数可对虚拟机的运行状态进行调整,掌握参数的含义可对虚拟机的运行模式有更深入理解。
使用JSCH执行命令并读取终端输出的一些使用心得
使⽤JSCH执⾏命令并读取终端输出的⼀些使⽤⼼得使⽤Jsch执⾏命令,并读取终端输出jschJsch是java实现的⼀个SSH客户端。
开发JSCH的公司是 jcraft:JCraft成⽴于1998年3⽉,是⼀家致⼒于Java应⽤程序和Internet / Intranet服务的应⽤程序开发公司。
Jcraft的总裁兼⾸席执⾏官是Atsuhiko Yamanaka博⼠在Yamanaka博⼠于1998年3⽉创⽴JCraft之前,他已经加⼊NEC公司两年了,从事软件的研究和开发。
Yamanaka博⼠拥有⽇本东北⼤学的信息科学硕⼠学位和博⼠学位。
他还获得了东北⼤学信息科学学⼠学位。
他的主题与计算机科学的数学基础有关,尤其是构造逻辑和功能编程语⾔的设计。
执⾏命令public static String executeCommandWithAuth(String command,SubmitMachineInfo submitMachineInfo,ExecuteCommandACallable<String> buffer) {Session session = null;Channel channel = null;InputStream in = null;InputStream er = null;Watchdog watchdog = new Watchdog(120000);//2分钟超时try {String user = submitMachineInfo.getUser();String host = submitMachineInfo.getHost();int remotePort = submitMachineInfo.getPort();JSch jsch = new JSch();session = jsch.getSession(user, host, remotePort);Properties prop = new Properties();//File file = new File(SystemUtils.getUserHome() + "/.ssh/id_rsa");//String knownHosts = SystemUtils.getUserHome() + "/.ssh/known_hosts".replace('/', File.separatorChar);//jsch.setKnownHosts(knownHosts)//jsch.addIdentity(file.getPath())//prop.put("PreferredAuthentications", "publickey");//prop.put("PreferredAuthentications", "password");//prop.put("StrictHostKeyChecking", "no");session.setConfig(prop);session.setPort(remotePort);session.connect();channel = session.openChannel("exec");((ChannelExec) channel).setPty(false);((ChannelExec) channel).setCommand(command);// get I/O streamsin = channel.getInputStream();er = ((ChannelExec) channel).getErrStream();BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));BufferedReader errorReader = new BufferedReader(new InputStreamReader(er, StandardCharsets.UTF_8));Thread thread = Thread.currentThread();watchdog.addTimeoutObserver(w -> thread.interrupt());channel.connect();watchdog.start();String buf;while ((buf = reader.readLine()) != null) {buffer.appendBuffer(buf);if (buffer.IamDone()) {break;}}String errbuf;while ((errbuf = errorReader.readLine()) != null) {buffer.appendBuffer(errbuf);if (buffer.IamDone()) {break;}}//两分钟超时,⽆论什么代码,永久运⾏下去并不是我们期望的结果,//加超时好处多多,⾄少能防⽌内存泄漏,也能符合我们的预期,程序结束,相关的命令也结束。
java运行一个外部程序并捕获输出的技巧
java运行一个外部程序并捕获输出的技巧
大家知道java运行一个外部程序并捕获输出吗?下面我们就给大家详细介绍一下吧!我们积累了一些经验,在此拿出来与大家分享下,请大家互相指正。
在Java中运行一个外部程序是使用ng.Runtime类的方法exec().该方法返回一个Process类。
如果你想捕获运行程序的输出,就要使用Process 类。
Process类有三个方法:. Process.getOutputStream(),Process.getInputStream(),Process.getErrorStream().分别对应于stdin,stdout,stderr。
因此如果想要捕捉该程序的输出,就要使用Process.getInputStream()。
下面我给的例子就是运行ping程序,然后把它的输出打印到屏幕上。
所产生的效果和直接运行ping 程序是一样的。
对于Process类的其他方法的使用例子,请大家下载我所提供jdk1.1类库API例子。
import java.io.*;class Main {
public static void main(String[] args) {
try {
String cmd = “ping “;。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在Java程序中截获控制台输出在Java开发中,控制台输出仍是一个重要的工具,但默认的控制台输出有着各种各样的局限。
本文介绍如何用Java管道流截取控制台输出,分析管道流应用中应该注意的问题,提供了截取Java程序和非Java程序控制台输出的实例。
即使在图形用户界面占统治地位的今天,控制台输出仍旧在Java程序中占有重要地位。
控制台不仅是Java程序默认的堆栈跟踪和错误信息输出窗口,而且还是一种实用的调试工具(特别是对习惯于使用println()的人来说)。
然而,控制台窗口有着许多局限。
例如在Windows 9x平台上,DOS控制台只能容纳50行输出。
如果Java程序一次性向控制台输出大量内容,要查看这些内容就很困难了。
对于使用javaw这个启动程序的开发者来说,控制台窗口尤其宝贵。
因为用javaw启动java程序时,根本不会有控制台窗口出现。
如果程序遇到了问题并抛出异常,根本无法查看Java运行时环境写入到System.out或System.err的调用堆栈跟踪信息。
为了捕获堆栈信息,一些人采取了用try/catch()块封装main()的方式,但这种方式不一定总是有效,在Java运行时的某些时刻,一些描述性错误信息会在抛出异常之前被写入System.out和S ystem.err;除非能够监测这两个控制台流,否则这些信息就无法看到。
因此,有些时候检查Java运行时环境(或第三方程序)写入到控制台流的数据并采取合适的操作是十分必要的。
本文讨论的主题之一就是创建这样一个输入流,从这个输入流中可以读入以前写入Java控制台流(或任何其他程序的输出流)的数据。
我们可以想象写入到输出流的数据立即以输入的形式“回流”到了Java程序。
本文的目标是设计一个基于Swing的文本窗口显示控制台输出。
在此期间,我们还将讨论一些和Java 管道流(PipedInputStream和PipedOutputStream)有关的重要注意事项。
图一显示了用来截取和显示控制台文本输出的Java程序,用户界面的核心是一个JTextArea。
最后,我们还要创建一个能够捕获和显示其他程序(可以是非Java的程序)控制台输出的简单程序。
一、Java管道流要在文本框中显示控制台输出,我们必须用某种方法“截取”控制台流。
换句话说,我们要有一种高效地读取写入到System.out和S ystem.err 所有内容的方法。
如果你熟悉Java的管道流PipedInputStream和PipedOutputS tream,就会相信我们已经拥有最有效的工具。
写入到PipedOutputStream输出流的数据可以从对应的PipedInputS tream输入流读取。
Java的管道流极大地方便了我们截取控制台输出。
Listing 1显示了一种非常简单的截取控制台输出方案。
【Listing 1:用管道流截取控制台输出】PipedInputS tream pipedIS = new PipedInputStream();PipedOutputS tream pipedOS = new PipedOutputStream();try {pipedOS.connect(pipedIS);}catch(IOException e) {System.err.println("连接失败");System.exit(1);}PrintStream ps = new PrintStream(pipedOS);System.setOut(ps);System.setErr(ps);可以看到,这里的代码极其简单。
我们只是建立了一个PipedInputStream,把它设置为所有写入控制台流的数据的最终目的地。
所有写入到控制台流的数据都被转到PipedOutputStream,这样,从相应的PipedInputS tream读取就可以迅速地截获所有写入控制台流的数据。
接下来的事情似乎只剩下在Swing JTextArea中显示从pipedIS流读取的数据,得到一个能够在文本框中显示控制台输出的程序。
遗憾的是,在使用Java管道流时有一些重要的注意事项。
只有认真对待所有这些注意事项才能保证Listing 1的代码稳定地运行。
下面我们来看第一个注意事项。
1.1 注意事项一PipedInputS tream运用的是一个1024字节固定大小的循环缓冲区。
写入PipedOutputS tream的数据实际上保存到对应的PipedInputStream的内部缓冲区。
从PipedInputStream执行读操作时,读取的数据实际上来自这个内部缓冲区。
如果对应的PipedInputStream输入缓冲区已满,任何企图写入PipedOutputStream的线程都将被阻塞。
而且这个写操作线程将一直阻塞,直至出现读取PipedInputS tream的操作从缓冲区删除数据。
这意味着,向PipedOutputStream写数据的线程不应该是负责从对应PipedInputStream读取数据的唯一线程。
假设线程t是负责从PipedInputStream读取数据的唯一线程;另外,假定t企图在一次对PipedOutputS tream的write()方法的调用中向对应的PipedOutputStream写入2000字节的数据。
在t线程阻塞之前,它最多能够写入1024字节的数据(PipedInputStream内部缓冲区的大小)。
然而,一旦t被阻塞,读取PipedInputStream的操作就再也不会出现,因为t是唯一读取PipedInputStream的线程。
这样,t线程已经完全被阻塞,同时,所有其他试图向PipedOutputStream写入数据的线程也将遇到同样的情形。
这并不意味着在一次write()调用中不能写入多于1024字节的数据。
但应当保证,在写入数据的同时,有另一个线程从PipedInputStream读取数据。
Listing 2示范了这个问题。
这个程序用一个线程交替地读取PipedInputStream和写入PipedOutputS tream。
每次调用write()向PipedInputStream的缓冲区写入20字节,每次调用read()只从缓冲区读取并删除10个字节。
内部缓冲区最终会被写满,导致写操作阻塞。
由于我们用同一个线程执行读、写操作,一旦写操作被阻塞,就不能再从PipedInputStream读取数据。
【Listing 2:用同一个线程执行读/写操作导致线程阻塞】import java.io.*;public class Listing2 {static PipedInputStream pipedIS = new PipedInputS tream();static PipedOutputStream pipedOS =new PipedOutputS tream();public static void main(String[] a){try {pipedIS.connect(pipedOS);}catch(IOException e) {System.err.println("连接失败");System.exit(1);}byte[] inArray = new byte[10];byte[] outArray = new byte[20];int bytesRead = 0;try {// 向pipedOS发送20字节数据pipedOS.write(outArray, 0, 20);System.out.println(" 已发送20字节...");// 在每一次循环迭代中,读入10字节// 发送20字节bytesRead = pipedIS.read(inArray, 0, 10);int i=0;while(bytesRead != -1) {pipedOS.write(outArray, 0, 20);System.out.println(" 已发送20字节..."+i);i++;bytesRead = pipedIS.read(inArray, 0, 10);}}catch(IOException e) {System.err.println("读取pipedIS时出现错误: " + e);System.exit(1);}} // main()}只要把读/写操作分开到不同的线程,Listing 2的问题就可以轻松地解决。
Listing 3是Listing 2经过修改后的版本,它在一个单独的线程中执行写入PipedOutputStream的操作(和读取线程不同的线程)。
为证明一次写入的数据可以超过1024字节,我们让写操作线程每次调用PipedOutputStream的write()方法时写入2000字节。
那么,在startWriterThread()方法中创建的线程是否会阻塞呢?按照Java运行时线程调度机制,它当然会阻塞。
写操作在阻塞之前实际上最多只能写入1024字节的有效载荷(即PipedInputStream缓冲区的大小)。
但这并不会成为问题,因为主线程(main)很快就会从PipedInputStream的循环缓冲区读取数据,空出缓冲区空间。
最终,写操作线程会从上一次中止的地方重新开始,写入2000字节有效载荷中的剩余部分。
【Listing 3:把读/写操作分开到不同的线程】import java.io.*;public class Listing3 {static PipedInputStream pipedIS =new PipedInputS tream();static PipedOutputStream pipedOS =new PipedOutputS tream();public static void main(String[] args) {try {pipedIS.connect(pipedOS);}catch(IOException e) {System.err.println("连接失败");System.exit(1);}byte[] inArray = new byte[10];int bytesRead = 0;// 启动写操作线程startWriterThread();try {bytesRead = pipedIS.read(inArray, 0, 10);while(bytesRead != -1) {System.out.println("已经读取" +bytesRead + "字节...");bytesRead = pipedIS.read(inArray, 0, 10);}}catch(IOException e) {System.err.println("读取输入错误.");System.exit(1);}} // main()// 创建一个独立的线程// 执行写入PipedOutputStream的操作private static void startWriterThread() {new Thread(new Runnable() {public void run() {byte[] outArray = new byte[2000];while(true) { // 无终止条件的循环try {// 在该线程阻塞之前,有最多1024字节的数据被写入pipedOS.write(outArray, 0, 2000);}catch(IOException e) {System.err.println("写操作错误");System.exit(1);}System.out.println(" 已经发送2000字节...");}}}).start();} // startWriterThread()} // Listing3也许我们不能说这个问题是Java管道流设计上的缺陷,但在应用管道流时,它是一个必须密切注意的问题。