I/O流量可表示非常多不同种类的输入源和输出目的地。它包含一个简单的字节流,基本数据(int、boolean、double等待),本地化字符,和对象。仅是简单地传递数据,另一些流能够操作和转换数据

不管这些流终于是怎么工作的。它们都给程序提供了同样的简单模型:一个流就是一组数据序列。程序使用一个输入流从一个数据源读取数据,一次读取一个单元(单元的划分依赖于流的实现类)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjE1MjYxOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

类似的,程序使用输出流来将数据写入目的地。一次写入一个单元

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjE1MjYxOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

程序使用字节流来输入或者输出八位的字节,全部的字节流都继承自InputStream或OutputStream

以下是一个简单的字节流操作的展示,将一个文件拷贝到还有一个文件

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; public class CopyBytes {
public static void main(String[] args)throws IOException { FileInputStream in = null;
FileOutputStream out = null; try {
in = new FileInputStream("xanadu.txt");
out = new FileOutputStream("outagain.txt");
int c; while ((c = in.read()) != -1) {
out.write(c);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}

复制是一个循环过程,一次从数据源取出一个字节,然后写入新文件。流程图例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjE1MjYxOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

字节流的操作是一种低端的IO操作,效率非常低,大部分情况下下,应该避免使用字节流,而选择一种合适的高端流。比方上例中,文件里存的都是字符数据。最好的选择是使用字符流

Java平台使用Unicode规范来存储字符数据。字符流会依据本地的字符集自己主动转换。在西语的本地化环境中,字符集一般是8位的ASCII码的超集

以下的样例相同是拷贝文件。差别是利用字符流,而非字节流

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class CopyCharacters {
public static void main(String[] args)throws IOException { FileReader inputStream = null;
FileWriter outputStream = null; try {
inputStream = new FileReader("xanadu.txt");
outputStream = new FileWriter("characteroutput.txt"); int c;
while ((c = inputStream.read()) !=-1) {
outputStream.write(c);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}

字节流是一个字节一个字节读写数据,而字符流是一个字符一字符的读写数据。字节流和字符流的read()方法均返回一个int型变量,不同的是。字节流的read()返回的int型变量代表的是一个字节后8位的数值,而字符流的read()返回的int型变量代表的是一个字符后16位的数值

字符流通常要处理的是比单个字符更大的单元,一个经常使用的单元就是“行”:一个拥有终结符的字符串。一个终结符能够是回车符(“\r”)、换行符(“\n”)等

import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException; public class CopyLines {
public static void main(String[] args)throws IOException { BufferedReader inputStream = null;
PrintWriter outputStream = null; try {
inputStream = new BufferedReader(newFileReader("xanadu.txt"));
outputStream = new PrintWriter(newFileWriter("characteroutput.txt")); String l;
while ((l = inputStream.readLine())!= null) {
outputStream.println(l);
}
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
}

字符流一般是字节流的“包装器”,字符流使用字节流来运行物理I/O操作,同事字符流处理字符和字节间的转换。比如,FileReader使用FileInputStream,而 FileWriter使用FileOutputStream。

有两个通用的字节到字符的桥梁:

OutputStreramWriter将输出的字符流转化为字节流

InputStreamReader将输入的字节流转换为字符流

可是无论怎样操作,最后都是以字节的形式保存在文件里的。

//将输出的字符流转化为字节流
String fileName="d:"+File.separator+"hello.txt";
File file=new File(fileName);
Writer out=new OutputStreamWriter(newFileOutputStream(file));
out.write("hello");
out.close(); //将输入的字节流转换为字符流
String fileName="d:"+File.separator+"hello.txt";
File file=new File(fileName);
Reader read=new InputStreamReader(newFileInputStream(file));
char[] b=new char[100];
int len=read.read(b);
System.out.println(newString(b,0,len));
read.close();

以上的样例中。大部分都是没有缓冲的I/O流,这意味着每次读写请求都是直接被底层的操作系统处理的。这会使程序的处理效率很低下。缓冲输入输出流就是为解决问题设计的

缓冲输入流从内存的缓冲区读取数据,在缓冲区空的时候才会调用底层的输入接口。类似的,输出流往内存的缓冲区写数据,在缓冲区满的时候才会调用底层的输出接口

程序能够使用“包装”给输入输出流加上缓冲特性

inputStream =new BufferedReader(new FileReader("xanadu.txt"));
outputStream =new BufferedWriter(new FileWriter("characteroutput.txt"));

有时候我们须要提前将缓冲区的内容写出。而不是等到缓冲区填满。这就须要进行flush操作。

通过调用输出流的flush函数能够清空缓存区。

一些带缓冲的输出流支持自己主动flush,某些关键的事件能够出发缓冲区的自己主动flush,比如,PrintWriter类在每次调用println或format方法时就会自己主动flush缓冲区

输入输出流常常涉及到格式化数据的转换与逆转换。Java平台提供了两套API:scanner API将格式化数据分解为单个的标记并依据其数据类型进行转换。format API将数据组装成整齐的适于人理解的数据格式

scanner默认使用空字符来切割数据(空字符包含空格键、tab键以及终结符,能够通过静态方法Character.isWhitespace(ch)来推断一个字符是否是空字符)。

import java.io.*;
import java.util.Scanner; public class ScanXan {
public static void main(String[] args)throws IOException { Scanner s = null; try {
s = new Scanner(newBufferedReader(new FileReader("xanadu.txt"))); while (s.hasNext()) {
System.out.println(s.next());
}
}finally {
if (s != null) {
s.close();
}
}
}
}

虽然scanner不是一种流对象,可是仍然须要使用close方法关闭

假设想使用别的标记作为分隔符,能够通过调用scanner的useDelimiter()来实现,此函数接受一个正則表達式来作为指定的分隔符,比如,想使用一个“逗号+随意个空字符”来作为分隔符。使用s.useDelimiter(",\\s*")来设定

scanner除了能够处理简单的字符串之外,还支持出char类型之Java的基本类型,包含BigInteger 和 BigDecimal。

usnumbers.txt存储以下数据。供以下的程序读取

1

2.5

abc

3.5

{}12

2

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.Locale; public class ScanSum {
public static void main(String[] args)throws IOException { Scanner s = null;
double sum = 0; try {
s = new Scanner(newBufferedReader(new FileReader("usnumbers.txt")));
s.useLocale(Locale.US); while (s.hasNext()) {
if (s.hasNextDouble()) {
sum += s.nextDouble();
} else {
s.next();
}
}
} finally {
s.close();
} System.out.println(sum);
}
}

输出:9 ,即全部数字之和

实现了格式化的流对象或者是PrintWriter(处理字符流)的实例。或者是PrintStream(处理字节流)的实例

经常使用的PrintStream对象是System.out和System.err,假设须要创建一个格式化的输出流。应该实例化PrintWriter,而非PrintStream

与全部的字节流和字符流一样,PrintStream和PrintWriter实现了对简单的字节和字符的write方法集。

此外。两者还都实现了同样的方法来将内部数据转换为格式化数据,有两个层次的格式化方法:

print和println方法以标准方式格式化单个的值

format方法差点儿能够依据输入的格式化字符串和精度要求,格式化随意数量的值

public class Root {
public static void main(String[] args) {
int i = 2;
double r = Math.sqrt(i); System.out.print("The square rootof ");
System.out.print(i);
System.out.print(" is ");
System.out.print(r);
System.out.println("."); i = 5;
r = Math.sqrt(i);
System.out.println("The squareroot of " + i + " is " + r + ".");
}
}

i和r被格式化了两次:第一次使用print的重载方法print(intarg0)(还有其它一系列的同名方法。如print(double arg0)、print(char [] arg0)等)来格式化。第二次通过Java编译器的自己主动转换(同一时候使用了toString()方法)

而format方法依据格式字符转格式化多元參数。格式字符串由嵌入了格式标识符的静态文本组成

public class Root2 {
public static void main(String[] args) {
int i = 2;
double r = Math.sqrt(i);
System.out.format("The square rootof %d is %f.%n", i, r);
}
}

输出:The square root of2 is 1.414214.

如上例所看到的。全部的格式标识符都已%開始

%d 表示格式化为十进制整数

%f表示格式化为十进制浮点数

%n 表示输出一个特定平台的行终结符

%x 表示格式化为十六进制整数

%s表示格式化为字符串

%tB 表示格式化为本地化的月份名称

等等

出%%和%n之外,全部的格式标识符必须匹配一个參数,否则会抛出异常

格式标识符之后还能够其它可选的标识符来进行更高层次的格式化。

System.out.format("%f,%1$+020.10f %n", Math.PI);

输出

3.141593,+00000003.1415926536

"%f,%1$+020.10f %n"之中,%代表格式字符串的開始。%1$代表參数的索引,+代表数值带符号,加号后面的0代表用0补全宽度要求,20代表宽度。.10代表小数精度。%n代表换行

<标识符代表匹配和前一个标识符同样的參数

关于格式字符串的具体使用能够參照相关API

程序常常须要通过命令行环境与用户进行交互。Java平台提供了两种交互方法:标准流(Standard Streams)和 控制台(Console)

默认情况下,标准流从键盘读取数据而且写入输出流来展示数据。同一时候也支持文件与程序间的IO操作。只是这是由命令行解释器控制的,而不是程序

Java平台支持三种标准流:标准输入流。通过System.in实现。标准输出流。通过System.out实现;标准错误流,通过System.err实现。标准输出流和标准错误流都属于输出流。用户能够将错误输出转移到文件里以便查询错误信息

标准流因为历史原因,被定义为字节流(PrintStream),而非字符流(PrintWriter)。虽然它们从技术实现上讲,是一种字节流,可是PrintStream使用了一种内置的字符流对象来仿真非常多字符流的特性

System.in是一种没有字符流特性的字节流,把System.in包装进InputStreamReader。能够把它当做字符流来使用

InputStreamReader cin = new InputStreamReader(System.in);

Console是比标准流更高级的实现,使用Console之前必须使用System.console()来确定Console是否可用(如不可用。返回null)

Console对象的readPassword方法支持安全的password输入:首先。该方法不会回显输入的password。其次,该方法返回的是一个字符数组。而不是字符串,所以password能够被覆写,尽快的从内存移除

import java.io.Console;
import java.util.Arrays;
import java.io.IOException; public class Password { public static void main (String args[])throws IOException { Console c = System.console();
if (c == null) {
System.err.println("Noconsole.");
System.exit(1);
} String login = c.readLine("Enteryour login: ");
char [] oldPassword =c.readPassword("Enter your old password: "); if (verify(login, oldPassword)) {
boolean noMatch;
do {
char [] newPassword1 =c.readPassword("Enter your new password: ");
char [] newPassword2 =c.readPassword("Enter new password again: ");
noMatch = !Arrays.equals(newPassword1, newPassword2);
if (noMatch) {
c.format("Passwords don'tmatch. Try again.%n");
} else {
change(login,newPassword1);
c.format("Password for%s changed.%n", login);
}
Arrays.fill(newPassword1, ' ');
Arrays.fill(newPassword2, ' ');
} while (noMatch);
} Arrays.fill(oldPassword, ' ');
} // Dummy change method.
static boolean verify(String login, char[]password) {
// This method always returns
// true in this example.
// Modify this method to verify
// password according to your rules.
return true;
} // Dummy change method.
static void change(String login, char[]password) {
// Modify this method to change
// password according to your rules.
}
}
<span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;">Data Streams用于支持Java基本类型(boolean,char, byte, short, int, long, float, and double)以及String的IO操作</span>

以下的实例展示了DataInputStream类和 DataOutputStream类的使用方法

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.EOFException; public class DataStreams{
static final String dataFile ="invoicedata"; static final double[] prices = { 19.99,9.99, 15.99, 3.99, 4.99 };
static final int[] units = { 12, 8, 13, 29,50 };
static final String[] descs = { "JavaT-shirt",
"Java Mug",
"Duke Juggling Dolls",
"Java Pin",
"Java Key Chain" }; public static void main(String[] args)throws IOException { DataOutputStream out = null; try {
out = new DataOutputStream(new
BufferedOutputStream(newFileOutputStream(dataFile))); for (int i = 0; i <prices.length; i ++) {
out.writeDouble(prices[i]);
out.writeInt(units[i]);
out.writeUTF(descs[i]);
}
} finally {
out.close();
} DataInputStream in = null;
double total = 0.0;
try {
in = new DataInputStream(new
BufferedInputStream(newFileInputStream(dataFile))); double price;
int unit;
String desc; try {
while (true) {
price = in.readDouble();
unit = in.readInt();
desc = in.readUTF();
System.out.format("Youordered %d units of %s at $%.2f%n",
unit, desc, price);
total += unit * price;
}
} catch (EOFException e) { }
System.out.format("For a TOTAL of:$%.2f%n", total);
}
finally {
in.close();
}
}
}

输出:

You ordered 12units of Java T-shirt at $19.99

You ordered 8units of Java Mug at $9.99

You ordered 13units of Duke Juggling Dolls at $15.99

You ordered 29units of Java Pin at $3.99

You ordered 50units of Java Key Chain at $4.99

For a TOTAL of:$892.88

DataInputStream和DataOutputStream仅仅能作为输入流的包装器使用,就是说必须给两者传入一个底层的字节流

writeUTF()方法以修正的UTF-8编码写入字符串,修正的UTF-8编码是一种变长的编码格式

须要注意的是,DataInputStream通过捕获EOFException异常来检測文件已到结尾,而不是像其它输入流那样,检測一个有效的返回值。

另外,特殊化的read方法(readInt()、readDouble()等)是与特殊化的write方法(writeInt()、writeDouble()等)严格相应的。这样的相应要靠编程者实现。

输入流包括的是简单的字节流,并没有指示出单个值的数据类型

在上面的样例中。有一个非常大的缺点:货币值是用浮点数。存储的,这不利于货币值的精确表示。尤其不利于十进制小数。由于常见的数值(比方0.1)并没有二进制表示法

货币值应该使用java.math.BigDecimal类型来表示,但是,BigDecimal不是java的基本类型,DataInputStream和DataOutputStream不能操作BigDecimal类型的数据,这就须要使用ObjectStreams来实现了

Object Streams包含ObjectInputStream和ObjectOutputStream,他们实现了ObjectInput接口和ObjectOutput接口,而ObjectInput接口和ObjectOutput接口是DataInput和DateOutput的子接口,这意味着ObjectStreams既能够实现Data Stream所能实现的基本数据操作,也能实现对象数据操作

import java.io.*;
import java.math.BigDecimal;
import java.util.Calendar; public class ObjectStreams {
static final String dataFile ="invoicedata"; static final BigDecimal[] prices = {
new BigDecimal("19.99"),
new BigDecimal("9.99"),
new BigDecimal("15.99"),
new BigDecimal("3.99"),
new BigDecimal("4.99") };
static final int[] units = { 12, 8, 13, 29,50 };
static final String[] descs = { "JavaT-shirt",
"Java Mug",
"Duke Juggling Dolls",
"Java Pin",
"Java Key Chain" }; public static void main(String[] args)
throws IOException,ClassNotFoundException { ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new
BufferedOutputStream(newFileOutputStream(dataFile))); out.writeObject(Calendar.getInstance());
for (int i = 0; i <prices.length; i ++) {
out.writeObject(prices[i]);
out.writeInt(units[i]);
out.writeUTF(descs[i]);
}
} finally {
out.close();
} ObjectInputStream in = null;
try {
in = new ObjectInputStream(new
BufferedInputStream(newFileInputStream(dataFile))); Calendar date = null;
BigDecimal price;
int unit;
String desc;
BigDecimal total = newBigDecimal(0); date = (Calendar) in.readObject(); System.out.format ("On %tA,%<tB %<te, %<tY:%n", date); try {
while (true) {
price = (BigDecimal)in.readObject();
unit = in.readInt();
desc = in.readUTF();
System.out.format("Youordered %d units of %s at $%.2f%n",
unit, desc, price);
total =total.add(price.multiply(new BigDecimal(unit)));
}
} catch (EOFException e) {}
System.out.format("For a TOTALof: $%.2f%n", total);
} finally {
in.close();
}
}
}

输出:

On 星期日, 十一月 16, 2014:

You ordered 12units of Java T-shirt at $19.99

You ordered 8units of Java Mug at $9.99

You ordered 13units of Duke Juggling Dolls at $15.99

You ordered 29units of Java Pin at $3.99

You ordered 50units of Java Key Chain at $4.99

For a TOTAL of:$892.88

当readObject()方法没有返回预期的对象类型时,强制转换可能会抛出ClassNotFoundException异常,在上例中。此异常肯定不会发生,所以没有使用try-catch语句

writeObject()和readObject()用起来非常easy。实际上包括着非常复杂的管理逻辑。

对上例中的Calendar类而言,仅封装了基本类型,这样的复杂性体现不出来,可是对于包括了其它对象的引用的对象。逻辑就不是那么简单了。readObject从流中重构对象,它不得不重构全部被该对象引用的对象。而这些被引用的对象还可能引用了很多其它的对象,在这样的情况下,writeObject会将该对象直接引用和间接引用的整个网络传递到流中。因此一个单独的writeObject方法可能会引发数量众多的对象被写入流中,在调用readObject时相同会发生类似的事情

下图是这样的操作逻辑的简单示意

对象a引用了对象b和c,而对象b又引用了对象d和e。在写入和读出时,须要对操作五个对象

假如两个引用了同一个对象的对象被写入同一个流中。那他们被读出时是不是也引用了同一个对象呢?答案是肯定的。虽然一个流中能够包括一个对象的无数次引用。可是它仅仅能有一个实例。

Object ob = newObject();

out.writeObject(ob);

out.writeObject(ob);

同一个对象被写入两次,然后读出

Object ob1 =in.readObject();

Object ob2 =in.readObject();

ob2和ob2是两个变量,可是引用了同一个对象

须要注意的是,仅仅有支持java.io.Serializable 或 java.io.Externalizable 接口的对象才干从ObjectStreams读取。

序列化是将对象状态转换为可保持或传输的格式(Byte流)的过程。

与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,能够轻松地存储和数据传输。序列化就是一种用来处理对象流的机制。所谓对象流也就是将对象的内容进行流化。能够对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。

序列化的特点:

(1)假设某个类可以被串行化,其子类也可以被串行化。假设该类有父类。则分两种情况来考虑,假设该父类已经实现了可串行化接口。则其父类的对应字段及属性的处理和该类同样。假设该类的父类没有实现可串行化接口。则该类的父类全部的字段属性将不会串行化。

假设父类没有实现串行化接口,则其必须有默认的构造函数(即没有參数的构造函数)。

否则编译的时候就会报错。在反串行化的时候,默认构造函数会被调用

(2)声明为static和transient类型的成员数据不能被串行化。由于static代表类的状态, transient代表对象的暂时数据;

(3)相关的类和接口:在java.io包中提供的涉及对象的串行化的类与接口有ObjectOutput接口、ObjectOutputStream类、ObjectInput接口、ObjectInputStream类。

一个类要想被序列化,即可必须实现java.io.Serializable接口,Serializable是一个标识接口,未定义不论什么方法。实现了这个接口之后。就表示这个类具有被序列化的能力。

import java.io.Serializable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream; /**
* 实现具有序列化能力的类
* */
public class Person implements Serializable{
public Person(){ } public Person(String name, int age){
this.name = name;
this.age = age;
} //覆写了toString方法
public String toString(){
return "姓名:" +name + " 年龄:" +age;
} private String name;
private int age;
} public class ObjectOutputStreamDemo{
public static void main(String[] args)throws IOException{
File file = new File("d:" +File.separator + "hello.txt");
ObjectOutputStream oos = newObjectOutputStream(new FileOutputStream(
file));
oos.writeObject(new Person("clf",25));
oos.close();
}
}

此时D盘中的hello.txt文件里是乱码,由于存储的是二进制数据,能够使用ObjectInputStream读取

import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectInputStream; public class ObjectInputStreamDemo{
public static void main(String[] args)throws Exception{
File file = new File("d:" +File.separator + "hello.txt");
ObjectInputStream input = newObjectInputStream(new FileInputStream(
file));
Object obj = input.readObject();
input.close();
System.out.println(obj);
}
}

输出:姓名:clf 年龄:25

当我们使用Serializable接口实现序列化操作的时候。假设一个对象的某一个属性不想被序列化保存下来,能够使用transientkeyword进行说明,比如上面的Person类,假设把name属性定义为

private transient String name;

输出为:姓名:null 年龄:25

java.io.Externalizable继承自java.io.Serializable接口。当对象实现了这个接口时。就能够灵活的控制它的序列化和反序列过程

Externalizable 接口定义了两个方法。writerExternal方法在序列化时被调用,能够在该方法中控制序列化内容,readExternal方法在反序列时被调用,能够在该方法中控制反序列的内容。

当一个类要使用Externalizable这个接口的时候。这个类中必需要有一个无參的构造函数,假设没有的话,在构造的时候会产生异常,这是由于在反序列话的时候会默认调用无參的构造函数。

Externalizable 接口定义了两个方法,writerExternal方法在序列化时被调用,能够再该方法中控制序列化内容,readExternal方法在反序列时被调用。能够在该方法中控制反序列的内容

import java.io.*;
import java.util.*; //本程序通过实现Externalizable接口控制对象序列化和反序列
public class UserInfo implements Externalizable {
public String userName;
public String userPass;
public int userAge; public UserInfo(){
} public UserInfo(String username,Stringuserpass,int userage){
this.userName=username;
this.userPass=userpass;
this.userAge=userage;
} //当序列化对象时,该方法自己主动调用
public void writeExternal(ObjectOutput out)throws IOException{
System.out.println("如今运行序列化方法");
//能够在序列化时写非自身的变量
Date d=new Date();
out.writeObject(d);
//仅仅序列化userName,userPass变量
out.writeObject(userName);
out.writeObject(userPass);
} //当反序列化对象时,该方法自己主动调用
public void readExternal(ObjectInput in)throws IOException,ClassNotFoundException{
System.out.println("如今运行反序列化方法");
Date d=(Date)in.readObject();
System.out.println(d);
this.userName=(String)in.readObject();
this.userPass=(String)in.readObject();
} public String toString(){
return "用户名:"+this.userName+";password:"+this.userPass+
";年龄:"+this.userAge;
}
}

另外还有管道流。主要用于线程间的通信

import java.io.*;
//管道流主要能够进行两个线程之间的通信。
/**
* 消息发送类
* */
class Sendimplements Runnable{
private PipedOutputStream out=null;
public Send() {
out=new PipedOutputStream();
}
public PipedOutputStream getOut(){
return this.out;
}
public void run(){
String message="hello ,Rollen";
try{
out.write(message.getBytes());
}catch (Exception e) {
e.printStackTrace();
}try{
out.close();
}catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 接受消息类
* */
class Reciveimplements Runnable{
private PipedInputStream input=null;
public Recive(){
this.input=new PipedInputStream();
}
public PipedInputStream getInput(){
return this.input;
}
public void run(){
byte[] b=new byte[1000];
int len=0;
try{
len=this.input.read(b);
}catch (Exception e) {
e.printStackTrace();
}try{
input.close();
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("接受的内容为"+(new String(b,0,len)));
}
}
/**
* 測试类
* */
class hello{
public static void main(String[] args)throws IOException {
Send send=new Send();
Recive recive=new Recive();
try{
//管道连接
send.getOut().connect(recive.getInput());
}catch (Exception e) {
e.printStackTrace();
}
new Thread(send).start();
new Thread(recive).start();
}
}

字节数组流。主要用于从内存中读写数据

import java.io.*;
class hello{
//ByteArrayInputStream主要将内容写入内容
//ByteArrayOutputStream 主要将内容从内存输出
public static void main(String[] args)throws IOException {
String str="ROLLENHOLT";
ByteArrayInputStream input=newByteArrayInputStream(str.getBytes());
ByteArrayOutputStream output=newByteArrayOutputStream();
int temp=0;
while((temp=input.read())!=-1){
char ch=(char)temp;
output.write(Character.toLowerCase(ch));
}
String outStr=output.toString();
input.close();
output.close();
System.out.println(outStr);
}
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

I/O概述和审查操作的更多相关文章

  1. docker概述及基础操作

    docker概述 容器技术已经成为应用程序封装和交付的核心技术容器技术的核心有以下几个内核组成CGroups-资源管理NamsSpace-进程管理SElinux-安全 由于是在物理机上实施隔离,启动一 ...

  2. WebService第一天——概述与入门操作

    一.概述 1.是什么 Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些 ...

  3. HDFS概述和Shell操作

    大数据技术之Hadoop(HDFS) 第一章 HDFS概述 HDFS组成架构 HDFS文件块大小 第二章 HDFS的Shell操作(开发重点) 1.基本语法 bin/hadoop fs 具体命令    ...

  4. Unix文件操作

    一.概述 Unix文件操作常用函数包括open.close.creat.lseek.dup.dup2.fcntl等, 其中open.creat. fcntl函数需要包含头文件<fcntl.h&g ...

  5. RxJava(八)concat符操作处理多数据源

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51568562 本文出自:[余志强的博客] 一.concat操作符概述 ...

  6. JAVA之旅(二十八)——File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤

    JAVA之旅(二十八)--File概述,创建,删除,判断文件存在,创建文件夹,判断是否为文件/文件夹,获取信息,文件列表,文件过滤 我们可以继续了,今天说下File 一.File概述 文件的操作是非常 ...

  7. VIM - 标准模式下简单操作

    1. 概述 标准模式下, 简单操作 移动 删除 复制粘贴 收益 熟练后, 编辑文本基本不需要鼠标操作了 思路 只讲最基本的, 避免初学时的混淆 把基本操作归类了, 方便理解 2. 准备 一篇篇幅较长的 ...

  8. Python学习之路day3-文件操作

    一.概述 作为IO操作的重要部分,文件操作需要经常用到,下面简述下python中操作文件的流程: 1. 打开文件,得到一个文件句柄并赋值给一个变量 f = open("test.txt&qu ...

  9. Spark学习摘记 —— RDD行动操作API归纳

    本文参考 参考<Spark快速大数据分析>动物书中的第三章"RDD编程",前一篇文章已经概述了转化操作相关的API,本文再介绍行动操作API 和转化操作API不同的是, ...

随机推荐

  1. 安装Microsoft .NET Framework 3.5 Service Pack 1回报1603错

    server升级了一下系统补丁(360安装),所有发现.net无法打开网站,提示" 因为无法创建应用程序域,因此未能运行请求.错误: 0x80070002 系统找不到指定的文件. " ...

  2. HDU 4686 Arc of Dream(递归矩阵加速)

    标题效果:你就是给你一程了两个递推公式公式,第一个让你找到n结果项目. 注意需要占用该公式的复发和再构造矩阵. Arc of Dream Time Limit: 2000/2000 MS (Java/ ...

  3. BZOJ 1834 ZJOI2010 network 网络扩展 Dinic+EK费用流

    标题效果:给定一个n积分m无向图边,每一方有一个扩展的成本c.代表扩张1费用的交通,寻求最大流量和扩大的最大流量k最小成本 第一问直接运行的最大流量 第二个问题将是连接到一个流的末端每个边缘的起点是正 ...

  4. JavaScript的"类"

    1. 基本创建“类”方式 var Class = function(){ var klass = function(){ this.init.apply(this, arguments); }; kl ...

  5. newlisp 接受jenkins带空格的参数

    jenkins有一个参数text种类,它能够以文本的段落拷贝作为参数 newlispThe program receives parameters are separated by spaces, 更 ...

  6. Quartz(GUI)图形界面程序----Quartz Web

    下载.设置和运行Quartz(GUI)图形界面程序----Quartz Web 一.获取Quartz Web程序(Quartz GUI).早期的 Quartz 框架开发者意识到一个 GUI 对于某类用 ...

  7. 基于AVR128单纯Modbus协议实施

    Modbus通信协议Modicon公司1979在发展中,适用于工业现场总线协议控制.Modbus通信系统包含芯片的节点,并与组合物可编程控制的公共传输线,它的目的是收集和监视多个节点的数据.Modbu ...

  8. C# 闭包问题

    C# 闭包问题-你被”坑“过吗? 引言 闭包是什么?以前看面试题的时候才发现这个名词. 闭包在实际项目中会有什么问题?现在就让我们一起来看下这个不太熟悉的名词. 如果在实际工作中用到了匿名函数和lam ...

  9. Android应用UI架构

    这个标题听起来可能有点大.事实上这里主要就是讨论一个应用程序的UI组件,是全用Activity还是全用Fragment.或者是二者皆有.以及使用Activity和Fragment的一些注意事项.  A ...

  10. MemberwishClone学习

    /* * Created by SharpDevelop. * User: My little flower basket * Date: 2013/7/12 * Time: 9:37 * * To ...