IO流是用来处理不同设备之间数据传输的。不同的流表示的是不同的输入输出设备。
0.File
(1)File是对文件对象的封装。File是对文件的属性,大小,位置,可读性等文件的信息的疯传的类。
(2)File表示的文件或者文件夹
(3)File可以作为参数传递给流的构造函数
1.一个重要的属性:文件分隔符File.separator
public static void test6(){
String s = File.separator;
System.out.println(s);//\
}
具有跨平台的特性
public static void test6(){
//File f = new File("C:\\Users\\huer\\Desktop\\text1.java");
File f = new File("C:"+File.separator+"Users"+File.separator+"huer\\Desktop\\text1.java");
}
2.File常见操作
(1)创建文件或文件夹f.createNewFile()
文件存在的话就不创建了。与流有区别:写入流一定会创建文件(可以控制覆盖和续写)
返回一个boolean值,表示创建成功或者失败。(2)删除
delete()
deleteOnExit() 退出的时候删除(用于临时文件的删除)
(3)判断文件是否存在
boolean exists()
这个是经常与IO流一起使用的,比如读入流,读的文件是必须存在的,所以可以用这个方法进行判断。
。。。。。
使用:
package cn.bishe.solrj;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class SolrJManager {
public static void main(String[] args) throws IOException {
/*String separator = File.separator;
File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a.txt");
System.out.println(f.getAbsolutePath());//C:\Users\huer\Desktop\a.txt
System.out.println(f.isFile());
System.out.println(f.isDirectory());
System.out.println(f.isAbsolute());//true
System.out.println(f.exists());//false
*/
/*String separator = File.separator;
File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a.txt");
boolean flag = f.createNewFile();
System.out.println(flag);//true
System.out.println(f.exists());//true
*/
/*String separator = File.separator;
File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a"+separator+"a.txt");
boolean flag = f.mkdirs();
System.out.println(f.getAbsolutePath());//C:\Users\huer\Desktop\a\a.txt
System.out.println(f.exists());//true
System.out.println(f.getName());//a.txt
System.out.println(f.getPath());//C:\Users\huer\Desktop\a\a.txt
*/
/*String separator = File.separator;
File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a");
String[] list = f.list();//列出文件名字集合
for(String s :list){
System.out.println(s);//a.txt
}*/
//文件过滤
/*String separator = File.separator;
File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a");
String[] list = f.list(new FilenameFilter(){
public boolean accept(File dir, String name) {
//这里只过滤文件名结尾是.txt的
return name.endsWith(".txt");
}
});
System.out.println(f.length());//文件没有长度,文件夹有
for(String s :list){
System.out.println(s);
}*/
//f.list()与f.listFiles()区别
//返回的一个是String[]集合,一个是File[]集合
/*String separator = File.separator;
File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a");
File[] list2 = f.listFiles(new FilenameFilter(){
public boolean accept(File dir, String name) {
//这里只过滤文件名结尾是.txt的
return name.endsWith(".txt");
}
});
System.out.println(list2.length);
for(File s :list2){
System.out.println(s.getName());
System.out.println(s.length());
}*/
}
//递归得到指定目录下文件的内容
//递归打印指定目录下的全部文件
//参数传进来的是路径
public static void showp(File dir){
//打印路径
System.out.println(dir);
File[] files = dir.listFiles();
for(File f:files){
if(f.isDirectory()){
showp(f);
}else{
System.out.println(f);//打印的文件就是文件完整路径
System.out.println(f.getName());//只会打印文件的名字
}
}
}
}
打印出带有层次的文件的结构
public class Demo {
public static void main(String[] args) throws IOException{
File file = new File("D:\\files\\数据库");
getFile(file,0);
}
//打印空格数目
public static String getKonge(int level){
StringBuilder s = new StringBuilder();//可以不断追加的容器
s.append("|--");//每次调用在结尾加|
for(int i=0;i<level;i++){
s.insert(0," ");//每次调用在最前面添加level个空格
}
return s.toString();
}
//打印出文件目录树结构
public static void getFile(File file,int level){
System.out.println(getKonge(level)+file);
level ++;
File[] f = file.listFiles();
for(File ff:f){
if(ff.isDirectory()){
getFile(ff,level+1);
}else{
System.out.println(getKonge(level+1)+ff);
}
}
}
}
显示的数据格式:
|--xxx
|--xxx
递归删除文件,不删除隐藏文件:
public static void removeFile(File dir){
File[] files = dir.listFiles();
for(File f:files){
if(!f.isHidden() && f.isDirectory()){
removeFile(f);
}else if(!f.isHidden() && !f.isDirectory()){
f.delete();
}
}
//删除目录
dir.delete();
}
public static void main(String[] args) throws IOException{
File f = new File("C:\\Users\\huer\\Desktop\\b");
removeFile(f);
}
迭代指定目录下的文件,找出所有的文件名字,将所有的文件名字放置到一个List中,然后将文件名字统一的放到一个文本文件中:
//将指定文件名放到List中
public static void fileToList(File dir,List<File> list){
File[] files = dir.listFiles();
for(File f:files){
if(f.isDirectory()){
fileToList(f,list);
}else{
if(f.getName().endsWith(".java")){
list.add(f);
}
}
}
}
//将List中的文件名字放到一个文件中
public static void writeToFile(List<File> list,String fileName){
BufferedWriter bw = null;
try{
bw = new BufferedWriter(new FileWriter(fileName));
for(File f:list){
bw.write(f.getAbsolutePath());
bw.newLine();
bw.flush();
}
}catch(Exception e){
throw new RuntimeException("写入文件发生异常");
}finally{
if(bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException("写入流关闭异常");
}
}
}
}
public static void main(String[] args) throws IOException{
File f = new File("C:\\Users\\huer\\Desktop\\a");
List<File> list = new ArrayList<File>();
String fileName = "C:\\Users\\huer\\Desktop\\text.txt";
fileToList(f,list);
writeToFile(list,fileName);
}
}
/*
* 硬盘上的文件结构:
* a----a1.java/a2.java/c(c1.java/c2.java)
*
* 运行结果:
* C:\Users\huer\Desktop\a\a1.java
C:\Users\huer\Desktop\a\a2.java
C:\Users\huer\Desktop\a\c\c1.java
C:\Users\huer\Desktop\a\c\c2.java
*/
一、字符流
(1)数据的存储都是二进制的形式。字符流是基于字节流的。也就是二进制byte字节到文本,所以文本的话就涉及到编码的问题。
(2)父类接口:Reader、Writer
(3)因为涉及到文本,所以有关于String的读写,看下面具体的介绍。
(一)文件
1.FileReader
(1)构造函数参数:(1)String(2)File
(2)读取的文件必须存在,不存在就会抛出异常
(3)常见操作:read()/read(char[])
close()关闭之前不会刷新缓冲区
2.FileWriter
(1)构造函数参数:(1)String(2)File
(2)两种形式:文件覆盖/文件续写:文件不存在会创建,文件存在的时候默认的是文件覆盖,在构造参数加true实现文件续写
FileWriter f = new FileWriter("a.txt");//文件会覆盖
FileWriter f = new FileWriter("a.txt",true);//文件不会覆盖,续写
(3)常见操作:writer(char[]/String/int),flush
close(关闭之前会先刷新缓存区)
(4)换行符:windows下默认的是\r\n,一般不会单独使用
3.例子
使用read(char[] )都文件的时候有换行符,所以写过去的时候不用写换行符。
public static void main(String[] args) {
//从文件读,读进char[],然后写进文件
FileReader fr = null;
FileWriter fw = null;
try{
//读的文件必须存在
fr = new FileReader("C:\\Users\\huer\\Desktop\\text1.java");
fw = new FileWriter("C:\\Users\\huer\\Desktop\\text2.java");
char[] ch = new char[1024];
int num = 0;
while((num = fr.read(ch))!=-1){
fw.write(ch, 0, num);//写进去实际的长度
fw.flush();//每写进去一点就进行刷新
}
}catch(Exception e){
throw new RuntimeException("文件读写失败");
}finally{
if(fr != null){
try {
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fw != null){
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
(二)缓冲流
使用在基础流上,为了提高效率的。关闭的时候只需要关闭最外层的缓冲流,基础流就不需要管了。
1.BufferedWriter
(1)构造函数参数:Writer
(2)常用方法:writer(int/char[]/String),flush,close
(3)尤其推荐的方法:newLine()换行符,可以跨平台
2.BufferedReader
(1)构造函数参数:Reader
(2)常用方法:read()/read(char[]),readLine(),close()
readLine()不会读到换行符,所以一般是和newLine()一起使用的
(3)尤其推荐的方法:readLine()读取一行,但是不会读取终止符,换行符这些
3.例子
public static void test4(){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new FileReader("C:\\Users\\huer\\Desktop\\text1.java"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\huer\\Desktop\\text2.java"));
String line = "";
while((line = br.readLine()) != null){
bw.write(line.toUpperCase());
bw.newLine();//写入换行符
bw.flush();
}
}catch(Exception e){
throw new RuntimeException("键盘读取发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("键盘读入发生异常");
}
}
if(bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException("控制台写入发生异常");
}
}
}
}
关闭的时候只需要关闭最外层的缓冲流。
4.LineNumberReader(BufferedReader子类),用来显示行号
(1)构造函数参数:Reader
(2)常用方法:readLine(),setLineNumber(),getLineNumber()
public static void test4(){
LineNumberReader br = null;
try{
br = new LineNumberReader(new FileReader("C:\\Users\\huer\\Desktop\\text1.java"));
String s = "";
while((s = br.readLine())!= null){
System.out.println(br.getLineNumber()+":"+s);
}
}catch(Exception e){
throw new RuntimeException("文件读写发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("关闭读入发生异常");
}
}
}
}
知识点
(1)解释字符流为什么要flush()?
因为字符设计到编码的问题,不能立刻输出到目的地,需要缓存一下,所以需要刷新。
(2)字符流涉及到文本,所以有读写String的操作
二、字节流
操作的是字节,比如图片传输。父类接口:输入流InputStream,输出流OutputStream。
(一)文件
1.FileInputStream
(1)构造函数参数:(1)String(2)File
(2)常用方法:read()/read(byte[])
(3)特别的方法:得到流中字节大小:available(),但是这个方法也不常用
2.FileOutputStream
(1)构造函数参数:(1)String(2)File
(2)常用方法:write(int/byte[]),close,flush
public static void test6(){
FileInputStream fi = null;
FileOutputStream fo = null;
try{
fi = new FileInputStream("C:\\Users\\huer\\Desktop\\图片\\a.jpg");
fo = new FileOutputStream("C:\\Users\\huer\\Desktop\\图片\\b.jpg");
byte[] b = new byte[1024];
int len = 0;
while((len=fi.read(b))!= -1){
fo.write(b,0,len);//为了保险起见,这里最好写上flush()
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(fi != null){
try {
fi.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fo != null){
try {
fo.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
(二)缓冲流
1.BufferedInputStream
(1)构造函数参数:InputStream
(2)常用方法:read()/read(byte[])
因为没有中文,所以没有读String的方法
2.BufferedOutputStream
(1)构造函数参数:OutputStream
(2)常用方法:write(int)/write(byte[])
知识点
字节流,操作的是byte,所以没有String的读写
三、转换流(字节流转为字符流)
转换流出现的原因?
(1)字符流最多只能以字节数组的形式读写,如果想使用BufferedReader/BufferedWriter的String的读写来提高效率的话,可以使用转换流。将字节流转为字符流。起点和终点还是原来的,只不过对流进行了包装,提高效率。
(2)编码的问题。使用转换流可以传入编码格式。
1.InputStreamReader
(1)构造函数参数:InputStream
(2)构造函数参数注意:可以传入编码参数
2.OutputStreamWriter
(1)构造函数参数:OutputStream
(2)构造函数参数注意:可以传入编码参数
(3)标准输入in:System.in---->InputStream
标准输出out: System.out--->PrintStream(父类是OutputStream)
public static void test3(){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\Users\\huer\\Desktop\\text1.java")));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = "";
while((line = br.readLine()) != null){
bw.write(line.toUpperCase());
bw.newLine();//写入换行符
bw.flush();
}
}catch(Exception e){
throw new RuntimeException("键盘读取发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("键盘读入发生异常");
}
}
if(bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException("控制台写入发生异常");
}
}
}
}
转换流,指明编码
public static void test3(){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new InputStreamReader(System.in));
//可以放进去英文,也可以中文,写入文件默认使用的编码就是GBK
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\huer\\Desktop\\text2.java"),"GBK"));
//写入文件编码使用utf-8会出现乱码
//bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\huer\\Desktop\\text2.java"),"utf-8"));
String line = "";
while((line = br.readLine()) != null){
if("over".equals(line)){//从键盘读,应该有结束的时候
break;
}
bw.write(line.toUpperCase());
bw.newLine();//写入换行符
bw.flush();
}
}catch(Exception e){
throw new RuntimeException("键盘读取发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("键盘读入发生异常");
}
}
if(bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException("控制台写入发生异常");
}
}
}
}
四、标准输入输出流
1.System.in(键盘):InputStream
2.System.out(控制台):PrintStream(它是OutputStream子类)
public static void test2(){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = "";
while((line = br.readLine()) != null){
if("over".equals(line)){//键盘需要有结束的时候
break;
}
bw.write(line.toUpperCase());
bw.newLine();//写入换行符
bw.flush();
}
}catch(Exception e){
throw new RuntimeException("键盘读取发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("键盘读入发生异常");
}
}
if(bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException("控制台写入发生异常");
}
}
}
}
readLine()没有换行符,所以写的时候要加上,使用BufferdWriter的newLine()或者Println():
public static void test1() {
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader(System.in));
String line = "";
while((line = br.readLine()) != null){//readLine不会读到换行符的
if("over".equals(line)){//从键盘读没有读到结尾的时候
break;
}
System.out.println(line.toUpperCase());//但是这里会打印出换行出来
}
}catch(Exception e){
throw new RuntimeException("键盘读取发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
键盘读,写入文件:
public static void test3(){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new FileWriter("C:\\Users\\huer\\Desktop\\text2.java"));
String line = "";
while((line = br.readLine()) != null){
if("over".equals(line)){//键盘读取需要有结束的时候
break;
}
bw.write(line.toUpperCase());
bw.newLine();//写入换行符
bw.flush();
}
}catch(Exception e){
throw new RuntimeException("键盘读取发生异常");
}finally{
if(br != null){
try {
br.close();
} catch (IOException e) {
throw new RuntimeException("键盘读入发生异常");
}
}
if(bw != null){
try {
bw.close();
} catch (IOException e) {
throw new RuntimeException("控制台写入发生异常");
}
}
}
}
知识点:
可以改变标准输入输出:
System.setIn(InputStream in)
System.setOut(PrintStream out)
InputStream in = System.in; PrintStream out = System.out
知识点:
字符流比字节流的一个优点是可以read一个String,字节流最多就是数组。
五、输出流:PrintStream与PrintWriter
1.区别
(1)PrintWriter的父类是Writer,PrintStream的父类是OutputStream。
(2)一个是字符流,一个是字节流,都没有对应的输入流。
(3)PrintStream的构造函数参数:OutputSream/File/String;
(4)PrintWriter的构造函数参数:OutputSream/File/String/Writer
(5)构造函数参数都可以设定自动刷新,都可以打印各种类型的数据
2.PrintWriter使用优先于BufferedWriter的原因
(1)PrintWriter输出的目的地可以是:String,File,OutputStream,Writer多样化
(2)PrintWriter可以设定自动刷新,但是如果使用BufferedWriter的话需要flush()
(3)BufferedReader读readLine(没有终止符)的时候,PrintWriter的println可以直接把终止符传输过去,比BufferedWriter的newLine()简单
//暂时不考虑从键盘输入停止的情况,暂时不考虑编码的问题
public static void test() throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(System.out,true);//自动刷新
String s = null;
while((s = br.readLine())!= null){
pw.println(s);//有换行符或者终止符
}
br.close();
pw.close();
}
PrintWriter的构造函数参数可以是Buffered,提高效率:
//暂时不考虑从键盘输入停止的情况,暂时不考虑编码的问题
public static void test() throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("C:\\Users\\huer\\Desktop\\text.txt")),true);//自动刷新
String s = null;
while((s = br.readLine())!= null){
pw.println(s);//输出终止符
}
br.close();
pw.close();
}
六、IO流输出异常信息
(1)异常输出流
printStackTrace(PrintStream s)
printStackTrace(PrintWriter s)
public static void test6(){
try{
int i = 1/0;
}catch(Exception e){
try {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");
String newDate = df.format(date);
PrintStream ps = new PrintStream("C:\\Users\\huer\\Desktop\\text2.java");
//先在流里面写上当前日期
ps.println(newDate);
//然后设置标准输出流
System.setOut(ps);
} catch (FileNotFoundException e1) {
throw new RuntimeException("日志文件创建失败");
}
e.printStackTrace(System.out);
}
}
/*
* 2018-35-16
java.lang.ArithmeticException: / by zero
at Test.test6(Test.java:158)
at Test.main(Test.java:176)
*/
七、系统信息集合Properties,集合与IO流结合的集合
Properties集合的数据结构:key-value
(1)Properties类,父类是Hashtable,是一个Map,不是IO流框架中的。
(2)是IO流与集合结合使用的集合
(3)注意的使用是通过IO流,加载并输出配置文件信息。但是在Web项目中关于配置文件都是框架自动管理的
从IO流中读取数据进Propeties集合:load(InputStream/Reader)
Propeties集合中的属性信息输出到IO流:store(OutputStream/Writer)
(4)Properties配置信息类与IO流使用的例子
a.配置文件控制用户登录次数(可以作为一个工具类)
登陆次数控制,使用Properties的例子:public static void test() throws IOException{
Properties p = new Properties();
File file = new File("C:\\Users\\huer\\Desktop\\text.ini");
if(!file.exists()){
file.createNewFile();
}
FileInputStream fi = new FileInputStream(file);
//将流中数据存储到属性文件集合中
p.load(fi);
int count = 0;
String value = p.getProperty("time");//读取配置信息
if(value != null){
count = Integer.parseInt(value);
if(count >= 5){
System.out.println("免费使用次数已经到期,请付费使用!");
return;
}
}
count++;
//修改配置信息,这里会覆盖掉原来存在的key-value
p.setProperty("time", count+"");
FileOutputStream fo = new FileOutputStream(file);
p.store(fo,"" );//重新写回文件
fi.close();
fo.close();
}
b.读取一个文件进Properties集合,然后存储进另一个文件
public static void test5(){
FileReader f = null;
Properties prop = new Properties();
OutputStream os = null;
try{
f = new FileReader("C:\\Users\\huer\\Desktop\\text.txt");
os = new FileOutputStream("C:\\Users\\huer\\Desktop\\text1.txt");
prop.load(f);//直接从流加载到集合中
System.out.println(prop+"-------");
//第二个参数是描述注释
prop.store(os, "hahaha");//直接将集合中的数据存储到流中
}catch(Exception e){
throw new RuntimeException("发生异常");
}finally{
if(f != null){
try {
f.close();
} catch (IOException e) {
throw new RuntimeException("发生异常");
}
}
if(os != null){
try {
os.close();
} catch (IOException e) {
throw new RuntimeException("键盘读入发生异常");
}
}
}
}
八、其他流
(一)合并输入流SequenceInputStream
(1)没有输出流,具有的功能是:合并多个输入流
(2)构造函数参数:(1)两个InputStream(2)多个InputStream的集合Enumeration
(3)关闭输入流的时候,只需要关闭合并流
//这个显示的结果存在的缺陷:多个文件中的存储到一个统一文件中的时候没有文件结尾的符号
public static void test11() throws Exception{
Vector<FileInputStream> ve = new Vector<FileInputStream>();
ve.add(new FileInputStream("C:\\Users\\huer\\Desktop\\t1.txt"));
ve.add(new FileInputStream("C:\\Users\\huer\\Desktop\\t2.txt"));
ve.add(new FileInputStream("C:\\Users\\huer\\Desktop\\t3.txt"));
Enumeration<FileInputStream> elements = ve.elements();
SequenceInputStream si = new SequenceInputStream(elements);
FileOutputStream fo = new FileOutputStream("C:\\Users\\huer\\Desktop\\tn.txt");
byte[] b = new byte[1024];
int s = 0;
while((s = si.read(b))!= -1){
fo.write(b,0,s);
fo.flush();
}
si.close();
fo.close();
}
(二)传输对象的流ObjectInputStream/ObjectOutputStream
(1)希望实现网络传输对象,那么这个对象需要实现Serialiable接口,这是一个标记接口。实现序列化
序列化就是持久化,就是可以进行网络传输的效果。
(2)可以读对象,可以写对象
(3)序列化,网络传输的是内存区的。静态的不能序列化。被transient修饰的成员变量不能序列化。
(三)管道流
(1)读写都是一个流,一般与线程同时使用,防止死锁
(2)连接的方式:PipedInputStream与PipedOutputStream可以创建的时候连接,也可以以后连接,但是必须连接之后进行使用
(3)演示用多线程使用管道流进行数据传输
public class Test{
public static void main(String[] args) throws Exception{
PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream();
in.connect(out);//必需建立连接
new Thread(new Write(out)).start();
new Thread(new Read(in)).start();
}
}
//读的线程
class Read implements Runnable{
private PipedInputStream pi = null;
public Read(PipedInputStream pi){
this.pi = pi;
}
@Override
public void run() {
try{
byte[] b = new byte[1024];
int len = pi.read(b);
String s = new String(b,0,len);
System.out.println(s);
pi.close();
}catch(Exception e){
throw new RuntimeException("管道读入流发生异常");
}
}
}
//写的线程
class Write implements Runnable{
private PipedOutputStream po = null;
public Write(PipedOutputStream po){
this.po = po;
}
@Override
public void run() {
try{
po.write("hello,world".getBytes());
po.close();
}catch(Exception e){
throw new RuntimeException("管道写入流发生异常");
}
}
}
(四)RandomAccessFile随机访问文件
(1)不是IO流体系中的一员,但是包是io包
(2)只能操作文件,进行文件读写控制,文件模式可以控制
(3)控制不同的位置的文件内容的读取和写入seek
import java.io.RandomAccessFile;
public class Test{
//写
public static void writeS() throws Exception{
RandomAccessFile ra = new RandomAccessFile("C:\\Users\\huer\\Desktop\\a.txt", "rw");
ra.write("你好啊".getBytes());
ra.close();
}
public static void readS() throws Exception{
RandomAccessFile ra = new RandomAccessFile("C:\\Users\\huer\\Desktop\\a.txt", "r");
byte[] b = new byte[1024];
int count = ra.read(b);
String s = new String(b,0,count);
System.out.println(s);
ra.close();
}
public static void main(String[] args) throws Exception {
writeS();
readS();
}
}
(*)注意:写入是以byte[],那么读出来的时候也要以byte[]
(五)操作基本数据类型的流对象DataInputStream/DataOutputStream
(1)写入的是二进制,所以是有乱码的,但是使用DataInputStream读出来的就没有乱码了
(2)读写各基本类型的数据
(3)指定编码的:writeUTF()/readUTF()
public class Test{
public static void test1() throws Exception{
DataOutputStream ra = new DataOutputStream(new FileOutputStream("C:\\Users\\huer\\Desktop\\text.txt"));
ra.writeInt(10);
ra.writeBoolean(true);
ra.writeDouble(20);
ra.close();
}
public static void test2() throws Exception{
DataInputStream ra = new DataInputStream(new FileInputStream("C:\\Users\\huer\\Desktop\\text.txt"));
int i1 = ra.readInt();
boolean i2 = ra.readBoolean();
double i3 = ra.readDouble();
System.out.println(i1);
System.out.println(i2);
System.out.println(i3);
ra.close();
}
public static void main(String[] args) throws Exception {
Test.test1();
Test.test2();
}
}
(六)文件的切割与合并
(1)切割就是一个输入流对应多个输出流
(2)合并就是多个输入流(可以使用合并流)对应一个输出流