java中的io流分为两类,字符和字节:
- OutputStream和InputStream字节流的父类,抽象。OutputStream有两个提供了实现的接口closable和flushable。
- Writer和Reader字符流的父类,抽象。
实际上在流的操作中,底层与文件进行读写的都是字节流,因为即使是字符流的对象,其最终实现读写的也是用的字节流。
- 操作文件的字节子类FileOutputStream和FileInputStream。
记住,这里面写出和读入的都是字节。
class useByteStream
{
/**
* 使用文件输出字节流
*
*/
public static void testFileOutputStream()
{
OutputStream out = null;
try
{
File f = new File(".//log//test.txt");
//out = new FileOutputStream(f);
out = new FileOutputStream(f,true); //追加方式记录到文件
String str = "Hello World!!!";
byte b[] = str.getBytes();
out.write(b);
out.close();
}
catch(FileNotFoundException e)
{
}
catch(IOException e)
{
}
}
/**
* 使用文件输入字节流
*/
public static void testFileInputStream()
{
InputStream out = null;
try
{
File f = new File(".//log//test.txt");
out = new FileInputStream(f);
String str = "Hello World!!!";
byte b[] = new byte[1000];
int len = out.read(b);
System.out.println(new String(b,0, len) );
out.close();
}
catch(FileNotFoundException e)
{
}
catch(IOException e)
{
}
}
};
- 操作文件的字符子类FileWriter和FileReader
class useCharStream
{
/**
* 使用文件字符输出流
*/
public static void testFileWriter()
{
Writer w = null;
try
{
File f = new File(".//log//test2.txt");
w = new FileWriter(f,true); //追加方式
w.write("hello world/r/n");
w.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
}
/**
* 使用文件字符输入流
*/
public static void testFileReader()
{
Reader w = null;
try
{
File f = new File(".//log//test2.txt");
w = new FileReader(f);
char c[] = new char[1024];
w.read(c);
System.out.println(c);
w.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
}
};
-
两个转换类,OutputStreamWriter,负责将写入字符流转为字节流,InputStreamReader,负责读取字节流转为字符流。
FileWriter的直接父类是OutputStreamWriter,并非Writer。
FileReader的直接父类是InputStreamReader,并非Reader。
因此,最终写入文件和从文件读出的都是字节流。以上都是基于文件流操作,接下来是基于内存操作流,如果只是写业务代码应该很少会用到。
- 内存操作流
ByteArrayInputStream/ByteArrayOutputStream。
class useMemoryStream
{
/**
* 使用内存操作流,字节
*/
public static void testByteArray()
{
String str = "Hello world";
ByteArrayInputStream bis = null;
ByteArrayOutputStream bos = null;
bis = new ByteArrayInputStream(str.getBytes());
bos = new ByteArrayOutputStream();
int temp =0;
while((temp=bis.read())!=-1)
{
char c = (char)temp;
bos.write(Character.toUpperCase(c));
}
String newStr = bos.toString();
try
{
bis.close();
bos.close();
}
catch(IOException e)
{
e.printStackTrace();
}
System.out.println(newStr);
}
};
- 另外,管道流可以实现两个线程之间的通信。
PipedInputStream 和 PipedOutputStream。
PipedOutputStream通过connect方法与PipedInputStream建立连接,后续PipedOutputStream.write的内容,就会PipedInputStream.read方法读取
class Send implements Runnable
{
private PipedOutputStream pos = null;
public Send()
{
this.pos = new PipedOutputStream();
}
public void run()
{
String str = "Hello world!!!";
try
{
try
{
Thread.sleep(2000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
this.pos.write(str.getBytes());
System.out.println("thread:"+Thread.currentThread().getId()+",Send string:"+str);
}
catch(IOException e)
{
e.printStackTrace();
}
try
{
this.pos.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public PipedOutputStream getPos()
{
return this.pos;
}
};
class Receive implements Runnable
{
private PipedInputStream pis = null;
public Receive()
{
this.pis = new PipedInputStream();
}
public void run()
{
byte b[] = new byte[1024];
int len =0;
try
{
len = this.pis.read(b); //阻塞方式
}
catch(IOException e)
{
e.printStackTrace();
}
try
{
pis.close();
}
catch(IOException e)
{
e.printStackTrace();
}
System.out.println("thread:"+Thread.currentThread().getId()+",receive:"+new String(b,0,len));
}
public PipedInputStream getPis()
{
return this.pis;
}
};
class pipedTest
{
public void pipedStream()
{
Send s = new Send();
Receive r = new Receive();
try {
s.getPos().connect(r.getPis());
}
catch(IOException e)
{
e.printStackTrace();
}
new Thread(r).start();
new Thread(s).start();
}
};
以上都是无缓存的,考虑到一般场景下,提高使用性能,最好使用有缓存的字符流:BufferedReader和BufferedWriter。
-
BufferedReader
只能接受输入为字符流,不能为字节流。所以有时候会使用InputStreamReader来转换字节流给字符流使用。还有BufferedWriterclass useBuffer { public static void testBufferReader() { BufferedReader buf = null; //此处用到了字节流转字符流的类InputStreamReader,这是因为BufferedReader只能接收字符流 buf = new BufferedReader(new InputStreamReader(System.in)); String str =null; try { str = buf.readLine(); } catch(IOException e) { e.printStackTrace(); } System.out.println("输出的内容为:"+str); } public static void testBufferWriter() { File f = new File(".//log//test2.txt"); try { //默认缓冲区大小 8K 可以通过 new BufferedWriter(new FileWriter(f),1024);指定大小为1K BufferedWriter out =new BufferedWriter(new FileWriter(f)); out.write("123321123355555", 0, 10); out.write("/r/n"); out.close(); } catch (IOException e) { e.printStackTrace(); } } };
-
SCanner类,输入数据类。
使用方法和BufferedReader类类似,并且方便验证数据类型。class useScan { public static void testScan() { Scanner scan = new Scanner(System.in); //以回车作为输入的结束符号,否则默认是空格 scan.useDelimiter("/r/n"); if(scan.hasNextInt()==true) { int str = scan.nextInt(); System.out.println("int "+str); } else { String str = scan.next(); System.out.println("string "+str); } } };
scan.hasNext
支持正则表达式。比如hasNext("^//d{4}-//d{2}-//d{2}$")
就是日期格式yyyy-MM-dd的正则表达式,通过next("^//d{4}-//d{2}-//d{2}$")
。
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/195824.html