JavaSE基础:IO
来源:互联网 发布:网络诽谤司法解释 编辑:程序博客网 时间:2024/06/01 07:49
------- android培训、java培训、期待与您交流! ----------
IO流分类
按流向:输入流、输出流;
按数据:字节流,字符流。
基类:
字节流:InputStream;OutPutStream
字符流:Reader;Writer;
字符流
数据的最常见体现形式是文件,先以操作文件为主来演示,需求:在硬盘上创建一个文件,并写入文字数据。Writer——OutputStreamWriter——FileWriter
方法:write(str /字符/字符数组/) 方法:将字符串写入到缓冲
flush()方法:刷新流对象中的缓冲的数据,将数据刷入到目的地中;
close()方法:关闭流资源,关闭前刷新流,将数据存入目的地中。
如果文件创建成功,一定要执行close方法关闭资源,需要捕捉IO异常;
FileWriter(File file, boolean append) 根据给定的 File 对象构造一个FileWriter对象
windows下的换行是 \r\n linux下是\n;
Reader——InputStreamReader——FileReader
方法:read(), 从输入流获取一个字符并作为数字返回,读到末尾,返回-1;
小程序,读取文件 输出到命令窗口;复制文件。
使用字符数组作为缓冲区,注意捕捉异常 。读写完毕,在finally中关闭流。
——————————————————
缓冲流:提高了对数据的读写效率。
BufferedWriterBufferedReader
缓冲区要结合流才能使用,再流的基础上对流的功能进行了增强。
关闭缓冲区就可以关闭缓冲区中的流对象,只要关闭缓冲区即可。
newLine()方法
BufferedReader 字符读取缓冲流
readLine()读取一行;
小练习:使用缓冲区复制一个文件。
自定义读取缓冲区,读取一行的方法。
LineNumberReader
装饰设计模式
当要对已有的对象进行功能增强时,可以定义一个类,将已有的对象传入,给予已有功能,并提供加强功能,那么自定义的该类就称为装饰类。
BufferReader其实就是装饰设计模式的体现。 readLine方法。
装饰类通常通过构造方法接收被装饰的对象,并给予被装饰对象提供更强的功能。
装饰模式比继承灵活,避免了继承的臃肿,降低了类与类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的相同,只不过提供了增强功能,所以装饰类和被装饰类属于一个体系。
字节流
InputStreamOutputStream
FileOutputStream fos = new FileOutputStream("xxxx.txt") ;
fos.write("abcdef".getBytes()) ; //字符串转为字节数组
//不需要刷新缓冲区,就可以写入数据,但是要关闭资源
fos.close() ;
FileInputStream fis = new FileInputStream("dddd.dd") ;
byte[] buf = new byte[fis.available()] ; //available 方法返回下一步可读取的字符数,换行符是两个字符
//返回一个刚刚好的缓冲区,不用循环了,这种方法比较危险,一般定义 byte[1024]
fis.read(buf) ;
System.out.println(new String(buf)) ;
fis.close() ;
————————————————————
缓冲区
BufferedInputStreamBufferedOutputStream
标准输入输出
FileInputStream in = System.in ;int by = in.read();
字节流转换字符流:
InputStreamReaderInputStreamReader sdr = new InputStreamReader(in) ;
BufferedReader br = new BufferedReader(sdr) ;
br.readline();
字符到字节流的桥梁
OutputStreamWriterFileOutputStream fos = System.out ;
OutputStreamWriter osw = new OutputStreamWriter(fos) ;
BufferedWriter bw = new BufferedWriter(osw) ;
bw.write(str );
bw.newLine() ; //加上换行
bw.flush() ;
键盘录入最常见写法。
1、键盘录入,输出控制台;2、键盘录入,输出文件;
3、读取文件,输出控制台。
流操作的基本规律:
该用哪一个流对象?
1、明确源和目的;
源:输入流 InputStream Reader
目的:输出流 OutputStream Writer
2、明确操作的数据是不是纯文本。
纯文本:字符流 Reader Writer
非纯文本:字节流 InputStream OutputStream
3、体系明确后,在确定使用那个具体的对象
通过设备区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
File类
方法:
1、创建:
boolean creatNewFile(); 在指定位置上创建文件,如果文件存在,返回false和输出流不同,输出流对象已建立就创建文件,如果文件存在,覆盖。
static File creatTempFile(xxx, xx); 创建临时文件
boolean mkdir("xx"); 创建目录
boolean mkdirs("xx\\xx\\xx"); 创建多级目录
2、删除
boolean delete(); 删除文件,成功返回true 。deleteOnExit(); 退出时删除
3、判断
boolean exists(); 判断是否存在boolean isDirectory(File); 判断是否为目录,必须先判断是否存在
boolean isFile(File); 判断是否为文件,必须先判断是否存在
boolean isHidden(); 判断是否隐藏
boolean isAbsolute(); 判断是相对路径或绝对路径。
4、获取信息
getName();getParent(); //返回绝对路径中的文件父目录
getPath();
String getAbsolutePath();获取绝对路径
File getAbsoluteFile();返回对象
long length();返回占用字节
long lastModified();获取最后修改时间;
long time = file.lastModified();
Date date = new Date(time);
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String strTime = df.format(date);
可以通过独立进程监控修改时间,如果被修改,通知程序加载新文件。
5、boolean renameTo(File dest); 重命名; 将文件重命名为dest,类似于剪切。
6、List
static File[] listRoots(); 列出系统根目录 如C:\ D:\String[] list(); 返回文件目录下的文件和文件名,,包括隐藏文件(一级目录),如果是文件,返回空,必须是目录。该目录必须存在。
Stringlist (FilenameFilter ff); 按文件名过滤;
|---FilenameFilter接口,重写方法 boolean accept(File dir,String name) ;
File[] listFiles();返回当前目录下的文件或目录的对象。
File[] listFiles(FileFilter filter);按文件过滤;
练习:删除一个带内容的目录:
在windows中,删除目录是从里面往外面删除的。public class RemoveDirTest {public static void main(String[] args) {File dir = new File("e:\\demodir");removeDir(dir);}public static void removeDir(File dir) {File[] files = dir.listFiles();for(File file : files){if(file.isDirectory()){removeDir(file);}else{System.out.println(file+":"+file.delete());}}System.out.println(dir+":"+dir.delete());}}
练习:遍历文件目录,将指定格式文件目录存储到一个文本列表。
递归:函数直接或间接的调用自身public class FileTest {public static void main(String[] args) {File dir = new File("d:\\java\\workspace");listAll(dir,0);}public static void listAll(File dir,int level) {System.out.println(getSpace(level)+dir.getName());//获取指定目录下当前的所有文件夹或者文件对象level++;File[] files = dir.listFiles(new FileFilter(){@Overridepublic boolean accept(File pathname) {return pathname.isDirectory()||pathname.getName().endsWith(".java");}});/*FilenameFilter filter = new FilenameFilter(){@Overridepublic boolean accept(File dir, String name) {return name.endsWith(".java");}};filter.accept(dir,file.getName());//过滤的另一种方式*/for(int x=0; x<files.length; x++){if(files[x].isDirectory()){listAll(files[x],level);}elseSystem.out.println(getSpace(level)+files[x].getName());}}private static String getSpace(int level) {StringBuilder sb = new StringBuilder();for(int x=0; x<level; x++){sb.append(" ");}sb.append("|--");return sb.toString();}}
Properties
Properties 是hashTable的子类,具备map集合的特点,键值对是字符串,是集合和IO相结合的容器,可以用于键值对形式的配置文件。在加载数据时,需要数据有固定格式,也就是键——值;
load(in); store(out,comments);comments为配置文件的首行说明文字,只能是英文字符
练习题:用于记录应用程序运行次数,如果次数已到,那么给出注册提示。
需要一个配置文件用于记录软件的使用次数。使用Properties配置文件可以实现应用程序数据的共享。public class PropertiesTest {public static void main(String[] args) throws IOException {getAppCount();}public static void getAppCount() throws IOException{//将配置文件封装成File对象。File confile = new File("count.properties");if(!confile.exists()){confile.createNewFile();}FileInputStream fis = new FileInputStream(confile);Properties prop = new Properties();prop.load(fis);//从集合中通过键获取次数。String value = prop.getProperty("time");//定义计数器。记录获取到的次数。int count =0;if(value!=null){count = Integer.parseInt(value);if(count>=5){throw new RuntimeException("使用次数已到,请注册,给钱!");}}count++;//将改变后的次数重新存储到集合中。prop.setProperty("time", count+"");FileOutputStream fos = new FileOutputStream(confile);prop.store(fos, "");fos.close();fis.close();}}
打印流:
print()方法可以将各种数据和数据类型原样打印。不会抛出IOException.
构造函数可以接受的数据类型,如果目标是输出流,可以加自动刷新标记
PrintStream 字节打印流
1、File对象 File2、字符串路径 String
3、字节输出流 OutputStream
PrintWriter 字符打印流
1、File对象 File2、字符串路径 String
3、字节输出流 OutputStream
4、字符输出流 Writer
特殊:write(int)方法:将int最低八位输出
读取键盘:
BufferedReader bufr = new BufferedReader (new InputStreamReader(System.in)) ;序列输入流
SequenceInputStream(Enmuration<InputStream> en)构造方法将多个读取流合并为一个读取流。
示例
public class SequenceInputStreamDemo {public static void main(String[] args) throws IOException {//需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。/* Vector<FileInputStream> v = new Vector<FileInputStream>();v.add(new FileInputStream("1.txt"));v.add(new FileInputStream("2.txt"));v.add(new FileInputStream("3.txt"));Enumeration<FileInputStream> en = v.elements();//---Vector的elements()方法返回该集合的枚举*/ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();for(int x=1; x<=3; x++){al.add(new FileInputStream(x+".txt"));}Enumeration<FileInputStream> en = Collections.enumeration(al);//---使用集合工具类的enumeration(Collection col)方法返回枚举./*final Iterator<FileInputStream> it = al.iterator(); //---局部内部类只能访问被final修饰的局部变量Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){//---自定义枚举@Overridepublic boolean hasMoreElements() {return it.hasNext();}@Overridepublic FileInputStream nextElement() {return it.next();}};*/SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream("1234.txt");byte[] buf = new byte[1024];int len = 0;while((len=sis.read(buf))!=-1){fos.write(buf,0,len);}fos.close();sis.close();}}
练习切割合并文件:
public class MergeFile {//---合并dir目录下的文件public static void main(String[] args) throws IOException {File dir = new File("c:\\partfiles");mergeFile(dir);}public static void mergeFile(File dir) throws IOException {//---合并文件 //获取指定目录下的配置文件对象。File[] files = dir.listFiles(new SuffixFilter(".properties"));if(files.length!=1)throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");File confile = files[0];//获取文件中配置信息:合并文件名,文件个数==================================Properties prop = new Properties();FileInputStream fis = new FileInputStream(confile);prop.load(fis);String filename = prop.getProperty("filename");int count = Integer.parseInt(prop.getProperty("partcount"));//获取该目录下的所有碎片文件。 ==============================================File[] partFiles = dir.listFiles(new SuffixFilter(".part"));if(partFiles.length!=(count-1)){throw new RuntimeException(" 碎片文件不符合要求,个数不对!应该"+count+"个");}//将碎片文件和流对象关联 并存储到集合中。 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();for(int x=0; x<partFiles.length; x++){al.add(new FileInputStream(partFiles[x]));}//将多个流合并成一个序列流。 Enumeration<FileInputStream> en = Collections.enumeration(al);SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream(new File(dir,filename));byte[] buf = new byte[1024];int len = 0;while((len=sis.read(buf))!=-1){fos.write(buf,0,len);}fos.close();sis.close();}}public class SuffixFilter implements FilenameFilter {private String suffix;public SuffixFilter(String suffix) {super();this.suffix = suffix;}@Overridepublic boolean accept(File dir, String name) {return name.endsWith(suffix);}}public class SplitFileDemo {//---切割文件,并将信息保存到配置文件中private static final int SIZE = 1024 * 1024;public static void main(String[] args) throws Exception {File file = new File("c:\\aa.mp3");splitFile(file);}private static void splitFile(File file) throws IOException {// 用读取流关联源文件。FileInputStream fis = new FileInputStream(file);// 定义一个1M的缓冲区。byte[] buf = new byte[SIZE];// 创建目的。FileOutputStream fos = null;int len = 0;int count = 1;/* * 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并。 * 这个信息为了进行描述,使用键值对的方式。用到了properties对象 */Properties prop = new Properties();File dir = new File("c:\\partfiles");if (!dir.exists())dir.mkdirs();while ((len = fis.read(buf)) != -1) {fos = new FileOutputStream(new File(dir, (count++) + ".part"));fos.write(buf, 0, len);fos.close();}//将被切割文件的信息保存到prop集合中。prop.setProperty("partcount", count+"");prop.setProperty("filename", file.getName());fos = new FileOutputStream(new File(dir,count+".properties"));//将prop集合中的数据存储到文件中。 prop.store(fos, "save file info");fos.close();fis.close();}}
对象流
ObjectInputStream 对象的反序列化ObjectOutputStream 对象序列化
对象序列化需要实现 Serializable 接口,可以指定序列化的版本号:
private static final long serialVersionUID = 1l;
static静态成员不能被序列化。只能序列化堆内存中的数据。
transient修饰符:瞬态化成员变量,使非静态成员不被序列化。
RandomAccessFile 随机访问文件类;
不算IO体系中的子类,直接继承自Object。具备读写功能,内部封装了一个数组,通过指针对数组中的元素操作,
可以通过getFilePointer获取指针位置,同时根据seek设置指针位置。
原理是其内部封装了字节读取流和输入流。
构造方法只能操作文件。
RandomAccessFile(File ,'r/rw');rw 代表读写模式
应用:断点续传功能
管道流
PipedInputStream / PipedOutputStreamPipedReader / PipedWriter
connect(Piped)连接管道流
需要使用多线程操作。
示例
public class PipedStream {public static void main(String[] args) throws IOException {PipedInputStream input = new PipedInputStream();PipedOutputStream output = new PipedOutputStream();input.connect(output);new Thread(new Input(input)).start();new Thread(new Output(output)).start();}}class Input implements Runnable{private PipedInputStream in;Input(PipedInputStream in){this.in = in;}public void run(){try {byte[] buf = new byte[1024];int len = in.read(buf);String s = new String(buf,0,len);System.out.println("s="+s);in.close();} catch (Exception e) {}}}class Output implements Runnable{private PipedOutputStream out;Output(PipedOutputStream out){this.out = out;}public void run(){try {Thread.sleep(5000);out.write("hi,管道来了!".getBytes());} catch (Exception e) {}}}
可以操作基本数据类型的流对象
DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流。DataInputStream(InputStream in) 使用指定的底层 InputStream 创建一个 DataInputStream。
写入UTF的方法:writeUTF("数据流"); 读取只能使用readUTF();
操作字节数组流
ByteArrayInputStream(byte[] buf) 创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。ByteArrayOutputStream() 创建一个新的 byte 数组输出流.通过toByteArray()和toString()获取数据.
close()方法无效;不会产生IOException;
writeTo(OutputStream out);将此 byte 数组输出流的全部内容写入到指定的输出流中。
用流的思想操作数组
操作字符数组
CharArrayReader
CharArrayWriter
操作字符串
StringReader
StringWriter
编码表
String str = new String("呵呵","UTF-8");byte[] buf = str.getBytes("UTF-8");
示例
public class Test {public static void main(String[] args) throws IOException {String str = "ab你好cd谢谢";//int len = str.getBytes("gbk").length;//for(int x=0; x<len; x++){//System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByByte(str, x+1));//}int len = str.getBytes("utf-8").length;for(int x=0; x<len; x++){System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByU8Byte(str, x+1));}}public static String cutStringByU8Byte(String str, int len) throws IOException {byte[] buf = str.getBytes("utf-8");int count = 0;for(int x=len-1; x>=0; x--){ //---判断截取的最后几位是什么字符。if(buf[x]<0)count++;elsebreak;}if(count%3==0) //---UTF-8的汉字是3个负数return new String(buf,0,len,"utf-8");else if(count%3==1)return new String(buf,0,len-1,"utf-8");else return new String(buf,0,len-2,"utf-8");}public static String cutStringByByte(String str,int len) throws IOException{byte[] buf = str.getBytes("gbk");int count = 0;for(int x=len-1; x>=0; x--){if(buf[x]<0)count++;elsebreak;}if(count%2==0)return new String(buf,0,len,"gbk");elsereturn new String(buf,0,len-1,"gbk");}}
------- android培训、java培训、期待与您交流! ----------
- JavaSE基础:IO
- 【JavaSE基础】------IO流【一】
- 黑马程序员----【javaSE基础】IO--字节流
- 黑马程序员----【javaSE基础】IO--字符流
- JavaSE基础--(二)IO部分
- Javase基础之IO流笔记
- Javase基础部分笔记之IO(一)
- Javase基础部分笔记之IO(二)
- JAVASE基础 Item -- IO流综合练习
- JAVASE基础-day20(IO(字节流))
- JAVASE基础-day22(IO(其他流)&Properties)
- javaSE-IO
- JAVASE IO
- javase io
- [javase]IO
- JavaSE IO
- JavaSe基础XX18——IO流_1
- JavaSe基础XX18——IO流_3
- Android避免ANR之StrictMode
- MediaPlayer报错prepareAsync called in state 8
- ipconfig 总结
- Visual Leak Detector 2.2.3 Visual C++内存检测工具
- 您也使用托管C++吗?(在托管代码中重用旧代码)
- JavaSE基础:IO
- ActivityGroup相关--getLocalActivityManager() 以及intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)用法
- K2 blackpearl 流程开发(二)
- 谈谈Unicode编码,简要解释UCS、UTF、BMP、BOM等名词
- _DllMain@12 already defined in CMPNT.obj 错误说明
- system.map 详解
- chkdsk修复磁盘命令详解
- 【2013微软校招面试题】设计一个栈,当栈满时,新入栈的元素循环回第一个元素的位置将其覆盖
- DM8168的互连与内存映射