IO流
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IO流相关的知识,希望对你有一定的参考价值。
IO流
1 输入流/输出流
IO流用来处理设备之间的数据传输
JAVA对数据的操作是通过流的方式
JAVA用于操作流的对象都在IO包中
流按操作数据分为两种,字节流和字符流
流按方向分为两种:输出流和输入流
从内存到外围设备称为输出(写) 从外围设备到内存称为输入(读)
2字符流/字节流
字节流
字符流:字节流读取文字数据后,不直接操作而是先查指定的编码表,获取对应的文字,在对这个文字进行操作。简单说,字符流就是字节流+编码表。
3 字符流----FileWriter
字节流的两个顶层父类
1 InputStrean 2 OutputStream
字符流的两个顶层父类
1 Reader 2 Writer
这些体系的子类都以父类名作为前缀
而且子类名的前缀就是该对象的功能
就从熟悉的文字开始
//需求:将一些文字存储到硬盘一个恩建中
操作文字数据,建议优先考虑字符流,而且要将数据从内存写到硬盘上,就要使用字符流中的输出流 Writer
硬盘的数据体现是文件所以选择FileWriter
package IO;
import java.io.FileWriter;
import java.io.IOException;
public class FileWritterDemo {
private static final String LINE_SEPARATOR=System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
//创建一个可以往文件中写入字符数据的字符输出流对象
/*
* 既然是往一个文件中写入文字数据,那么在创建文件时,必须明确该文件(用于存储数据的目的地)
*
*如果文件不存在,则会自动创建
*如果文件存在,则会被覆盖
*/
FileWriter fw=new FileWriter("demo.txt",true);
/*
* 调用Writer对象中的write方法,写入数据
*
*其实数据写入到临时存储缓冲区中
*
*
*如果构造函数中加入true可以实现对文件进行续写
*
*/
fw.write("abcdev"+LINE_SEPARATOR+"hahaha");
fw.write("123");
/*
* 进行刷新,将数据直接写入到目的地
*/
fw.flush();
/*关闭此流 释放资源*/
fw.close();
}
}
4 IOException处理
package IO;
import java.io.FileWriter;
import java.io.IOException;
public class IOExceptionDemo {
private static final String LINE_SEPARATOR=System.getProperty("line.separator");
public static void main(String[] args) {
FileWriter fw=null;
try {
fw=new FileWriter("k:\\demo.txt");
fw.write("abcdev"+LINE_SEPARATOR+"hahaha");
fw.close();
} catch (IOException e) {
System.out.println(e.toString());
}
finally
{ if(fw!=null)
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException("关闭失败");
}
}
}
}
5 字符读取流---读取方式一
package IO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
/*
*
*1 创建读取字符数据的流对象
*
*在创建读取流对象时,必须要明确被读取的文件,一定要确定文件是存在的
*
*用一个读取流关联一个已存在文件
*/
FileReader fr=new FileReader("demo.txt");
//用Reader中的read方法读取字符
int ch=fr.read();
System.out.println(ch);
ch=fr.read();
System.out.println((char)ch);
ch=fr.read();
System.out.println(ch);
ch=fr.read();
System.out.println(ch);
/*
*
* while((ch=fr.read())!=-1)
* {
* system.println((char)ch);
* }
*
*
*
*
*/
fr.close();
}
}
6 字符读取方式2
package IO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo2 {
public static void main(String[] args) throws IOException {
/*
*
*1 创建读取字符数据的流对象
*
*在创建读取流对象时,必须要明确被读取的文件,一定要确定文件是存在的
*
*用一个读取流关联一个已存在文件
*/
FileReader fr=new FileReader("demo.txt");
/*
*使用read(char[])读取文本文件数据
*/
/*
* 创建字符数组
*/
char []buf=new char[3];
int num=fr.read(buf);//将读取的字符存储到数组中
System.out.println(num+":"+new String(buf,0,num));
int num1=fr.read(buf);//将读取的字符存储到数组中
System.out.println(num1+":"+buf);
int len=0;
fr.close();
}
}
package IO;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileReadAndWrite {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("1.txt");
FileWriter fw=new FileWriter("2.txt");
char []buff=new char[1024];
int len;
while((len=(fr.read(buff)))!=-1)
{
fw.write(buff, 0, len);
fw.flush();
}
if(fr!=null)
fr.close();
if(fw!=null)
fw.close();
}
}
7字符流缓冲区
缓冲区的出现提高了对数据的读写效率。
对应类
BufferedWriter
BufferedReader
缓冲区要结合流才可以使用(相当于我们不用自己创建数组)
在流的基础上对流的功能进行了增强
BufferedWriter
package IO;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferDemo {
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("1.txt");
//为了提高写入的效率,使用了字符流的缓冲区
//创建了一个字符写入流的缓冲区对象 并和指定要被缓冲的流对象相关联
BufferedWriter bufw=new BufferedWriter(fw);
//使用缓冲区的写入的方法将数据写入缓冲区中
bufw.write("abcdefswddd");
bufw.newLine();
bufw.write("abc");
//使用缓冲区的刷新方法将数据刷新到目的地中
bufw.flush();
//关闭缓冲区 流也会关
bufw.close();
}
}
BufferedReader
package IO;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("2.txt");
BufferedReader bufr=new BufferedReader(fr);
String line=null;
while((line=(bufr.readLine()))!=null)
{
System.out.println(line);
}
bufr.close();
}
}
BufferedReader的readline方法 和BufferedWriter的newLine方法较为常用
8字节流基本演示
package IO;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileReadAndWrite {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("1.txt");
int ch;
/*while((ch= fis.read())!=-1)
{
System.out.println((char)ch);
}
*/
byte []buf=new byte[1024];
int len;
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
}
}
不需要使用flush方法 具体使用请查看API
9键盘录入
package myNewIo;
import java.io.IOException;
import java.io.InputStream;
public class KeyBoardDemo {
public static void main(String[] args) throws IOException {
InputStream in=System.in;
int ch=in.read();
System.out.println(ch);
int ch1=in.read();
System.out.println(ch1);
}
}
不需要关闭流 (因为它是默认设备)
10 转换流
package myNewIo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class TranslateStream {
public static void main(String[] args) throws IOException {
//字节流
InputStream in=System.in;
OutputStream out=System.out;
//转换流->转成字符流,就能像操作字符一样
InputStreamReader isr=new InputStreamReader(in);
OutputStreamWriter osw=new OutputStreamWriter(out);
//装饰
BufferedReader bufr=new BufferedReader(isr);
BufferedWriter bufw=new BufferedWriter(osw);
String line=null;
while((line=bufr.readLine())!=null)
{
if(line.equals("over"))
{
break;
}
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
}
11 流操作基本规律
之所以要弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。
想要知道开发时用哪个对象。只要通过四个明确。
1 明确源和目的
源:InputStream 或者Reader
目的 OutputStrean 或者 Writer
2 明确数据是否是纯文本
源:是纯文本 Reader
否 InputStream
目的 是纯文本:Writer
否:OutputStream
到这里就可以明确需要中具体要用到哪个体系
3明确具体的设备
源设备
硬盘:File
键盘:System.in
内存:数组
网络: socket流
目的设备:
硬盘 File
控制台 Systen.out
内存 数组
网络 socket流
4 是否需要额外功能
12 转换流的编码解码。
字符串用的码表是本地系统用的码表
JAVA内置的码表是UNICODE 字符类型就是这个码表识别的
其实FileWriter就等同于 转换流加本地编码表(如果要自己指定编码表,就必须使用转换流指定编码表)
13File类
用来将文件或者文件夹封装成对象
方便对文件和文件夹的属性信息进行操作
File对象可以作为作为参数传递给流的构造函数
了解File类的常用方法
package Fiie;
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
constructorDemo();
}
private static void constructorDemo() {
/*
* 可以将一个已存在的或者不存在的文件或者目录封装成FILE对象
*/
File f1=new File("d:\\a.txt");
File f2=new File("d:\\","a.txt");
File f=new File("c:\\");
File f3=new File(f,"a.txt");
File f4=new File("c:"+File.separator+"abc"+File.separator+"a.txt");
}
}
1 * File对象常见方法(文件或者目录操作)
package Fiie;
import java.io.File;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) {
/* 1获取
* 1.1 获取文件名称
* 1.2 获取文件路径
* 1.3 获取文件大小
* 1.4获取文件修改时间
*/
File file=new File("1.txt");
String name=file.getName();
String abspath=file.getAbsolutePath();
String path=file.getPath();
long len=file.length();
long time=file.lastModified();
Date date=new Date(time);
DateFormat dateFormat=DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time=dateFormat.format(date);
System.out.println("name:"+name);
System.out.println("abspath:"+abspath);
System.out.println("path:"+path);
System.out.println("len:"+len);
System.out.println("time:"+str_time);
}
}
2创建和删除
package Fiie;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
/*
* 2 创建和删除
*/
// File f=new File("x.txt");
//存在则不创建 不存在则创建(与IO流不一样)
//boolean b=f.createNewFile();//创建
// System.out.println("b="+b);
//删除
// boolean b1=f.delete();
// System.out.println("b1="+b1);
//创建目录
File f1=new File("abc");
boolean b3=f1.mkdir();
System.out.println("b3="+b3);
//创建多级目录
File f2=new File("bc\\dd\\ds\\dssw\\d\\s\\dddfa\\ffwas\\ffsa");
boolean b4=f2.mkdirs();
System.out.println("b4="+b4);
f2.delete(); //删除最里面的目录
}
}
3 判断
package Fiie;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
/*
* 判断
*/
File f=new File("1.txt");
boolean b=f.exists(); //判断文件是否存在
System.out.println("b="+b);
System.out.println(f.isFile()); //要先判断是否存在
System.out.println(f.isDirectory());
}
}
4 重命名
package Fiie;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
/*
* 重命名 路径一样会改名,路径不一样会剪切
*/
File f1=new File("c:\\a.txt");
File f2=new File("c:\\b.txt");
f1.renameTo(f2);
}
}
5 系统根目录和容量空间
package Fiie;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
/*
* 系统根目录和容量空间
*/
File []file=File.listRoots();
for(File f:file)
System.out.println(f);
File file1=new File("d:\\");
System.out.println("getFreeSpace:"+file1.getTotalSpace());
}
}
6 获取目录内容
package Fiie;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
File f=new File("e:\\");
String []names=f.list();
for(String s:names)
System.out.println(s);
}
}
7获取当前目录内容
package Fiie;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
/*
* 获取当前目录下的文件以及文件夹的名称,包含隐藏文件
* 调用List方法的File对象中封装的必须是目录
* 否则会发生NullPointerException
* 如果访问的是系统级目录也会发生空指针异常
*
*
* 如果目录存在 但是没有内容 会返回0长度的数组
*/
File f=new File("e:\\");
String []names=f.list();
for(String s:names)
System.out.println(s);
}
}
8 过滤器(当需要过滤时 寻找对应的接口 并实现方法)
package Fiie;
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
File dir=new File("e:\\javacode\\IO2\\src\\OtherIo");
String []names=dir.list(new FilterByName());
for(String name:names)
{
System.out.println(name);
}
}
}
package Fiie;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
public class FilterByName implements FilenameFilter {
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
}
还有各种过滤器 需要时查找API
9
Properties集合
package Fiie;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
/*
*
* Map
* ----HashTable
* ---------Properties
*
*
* Properties集合
*
* 特点:
* 1 该集合中的键和值都是字符串类型
* 2 集合中的数据可以保存到流中,或者从流获取
*
* 通常该集合用于操作键值对形式存在的配置文件
*
*
*/
/*
* 集合的存和取
*
*/
public static void main(String[] args) throws IOException {
//propertiesDemo();
//method_demo3();
method_demo4();
}
private static void method_demo4() throws IOException {
//集合中的数据来自一个文件
// 必须保证该文件的数据是键值对
//需要使用读取流
Properties prop=new Properties();
FileInputStream fis= new FileInputStream("info.txt");
//使用load方法
prop.load(fis);
prop.list(System.out);
}
private static void method_demo3() throws IOException {
//创建一个Properties集合
Properties prop=new Properties();
//存入元素
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","30");
prop.setProperty("wangwu","30");
prop.setProperty("lisi","36");
//想要将这些集合中的字符键值信息持久化存储到文件中
//需要关联输出流
FileOutputStream fos=new FileOutputStream("info.txt");
//将集合中数据存储到文件中,使用Store方法
prop.store(fos, "name+age");
fos.close();
}
public static void propertiesDemo()
{
//创建一个Properties集合
Properties prop=new Properties();
//存入元素
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","30");
prop.setProperty("wangwu","30");
prop.setProperty("lisi","36");
//取出元素
Set<String>names=prop.stringPropertyNames();
for(String name:names)
{
String value=prop.getProperty(name);
System.out.println(name+":"+value);
}
prop.list(System.out);
}
}
10 IO包的其它流
Print系列也是属于装饰 提供额外功能
PrintSream
package demo1;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamDemo {
public static void main(String[] args) throws IOException {
/*
* PrintStream
* 1 提供了打印方法对多种数据类型值进行打印,并保持数据的表示形式
* 2 它不抛IOEXCEPTION
*
*
* 构造函数 它接收三种类型的值
* 1 字符串路径
* 2 File对象
* 3 字节输出流
*/
PrintStream out=new PrintStream("print.txt");
out.write(97);
out.print(97);//保持原样 写入
out.close();
}
}
PrintWriter
package demo1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
/*
* PrintWriter:字符打印流
*
* 构造函数参数
* 1 字符串路径
* 2 File对象
* 3 字节输出流
* 4 字符输出流
*/
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(System.out);
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
out.flush();
}
out.close();
bufr.close();
}
}
11 序列流
package demo1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceInputStream {
public static void main(String[] args) throws Exception {
/*
* 需求:将1.txt 2.txt 3.txt 文件中的数据合并到一个文件中
*
*
*/
ArrayList<FileInputStream> v=new ArrayList();
v.add(new FileInputStream("1.txt"));
v.add(new FileInputStream("2.txt"));
v.add(new FileInputStream("3.txt"));
Enumeration<FileInputStream> en=Collections.enumeration(v);
SequenceInputStream sis=new SequenceInputStream(en);
FileOutputStream fos=new FileOutputStream("4.txt");
byte []buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
这个还可以做到文件合并
通过以前的流还可以做到文件合并
12对象序列化和反序列化
package demo1;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectSequenceDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos =new FileOutputStream("obj.object");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(new Person("小李",22));
oos.close();
fos.close();
}
}
package demo1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectSequenceDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis =new FileInputStream ("obj.object");
ObjectInputStream ois=new ObjectInputStream (fis);
Object obj=ois.readObject();
Person p=(Person)obj;
System.out.println(p.getAge()+":"+p.getName());
ois.close();
fis.close();
}
}
保证在类文件修改后 仍然可以读取(即保证版本一样 就需要自己定义标记号
private static final long serialVersionUID)
在数据前修饰 translent 可以保证不写入文件
13随机访问文件
package demo1;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessDemo {
public static void main(String[] args) throws IOException {
/*
* RandomAccessFile
* 一看这个名字,好像不是文件体系的对象
*
* 特点:
* 1 该对象既能读,又能写
* 2 该对象内部维护了一个byte数组。并通过指针可以操作数组中的元素
* 3 可以通过getFilePointer方法获取指针的位置,并通过seek方法设置指针位置
* 4 其实该对象就是将字节输入流和输出流进行了封装
* 5 该对象的源和目的只能是文件,通过构造函数就可以看出
*/
//使用 RandomAccessFile对象写入一些人员信息。比如姓名和年龄
writeFile();
}
public static void writeFile() throws IOException
{
RandomAccessFile raf=new RandomAccessFile("random.txt", "rw");
raf.write("张三".getBytes());
raf.write(‘你‘);
raf.close();
}
}
至于读 就不说了 这个对象的最大特点就是能更方便的操作数据。(int long byte等等)
14管道流
15 简单的编码解码
String s=”你好”;
Byte []b=s.getbytes(可以指定字符集);
以上是关于IO流的主要内容,如果未能解决你的问题,请参考以下文章