java(十一)IO流

深度遍历演示:

package day22;

import java.io.File;

public class FileTest {

/**

* 需求:对指定目录进行所有内容的列出。(包含子目录,前面学的都只能列出当前目录内容,子目录不行)

* 也可以理解为深度遍历。

*/

public static void main(String[] args) {

File dir=new File("e:\\javatest");

listAll_2(dir,0);

}

public static void listAll_1(File dir) {

System.out.println("dir:"+dir.getAbsolutePath());

//获取指定目录下当前的所有文件或者文件对象

File[] files=dir.listFiles();

for(int x=0;x<files.length;x++){

if(files[x].isDirectory()){

listAll_1(files[x]);                 //这就是递归

}

else

System.out.println("file:"+files[x].getAbsolutePath());

}

}

public static void listAll_2(File dir, int level) {        //定义一个计数器,记录当前文件的层级,从而决定前面加几个空格,为什么不在方法中定义?这就和递归有关了。

System.out.println(getSpace(level)+dir.getName());

level++;

File[] files=dir.listFiles();

for(int x=0;x<files.length;x++){

if(files[x].isDirectory()){

listAll_2(files[x],level);                 //这就是递归

}

else

System.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("   ");

}

return sb.toString();

}

}

上面代码中涉及到了递归,接下来就学习一下递归的知识。

递归: 函数自身直接或者间接地调用到了自身。

* 什么时候使用?

* 一个功能在被重复使用,并且每次使用时,参与运算的结果和上一次调用有关。

* 这时可以用递归来解决问题。

* 注意:1.递归必须明确条件,否则容易栈溢出

* 2.递归的次数别太多,否则栈溢出异常。

package day22;

public class DiGuiDemo {

/**

* 递归演示。

*/

public static void main(String[] args) {

/*

* 递归:函数自身或者直接或者间接调用到了自身

*   什么时候使用?

* 一个功能在被重复使用,并且每次使用时,参与运算的结果和上一次调用有关。

* 这时可以用递归来解决问题

* 注意:1.递归必须明确条件,否则容易栈溢出

* 2.递归的次数别太多,否则栈溢出异常。

*/

show();

}

public static void show(){

toBin(6);         //把一个数转换成二进制

}

//直接调用自身

public static void toBin(int i) {

if(i>0){

toBin(i/2);

System.out.print(i%2);

}

}

//间接调用自身

public static void method(){

bala();

}

public static void bala(){

method();

}

}

Properties集合

* Map

*   |--Hashtable;

*   |--Properties;

*

* Properties集合特点:

* 1.该集合中的键和值都是字符串。

* 2.集合中的数据可以保存到流中,或者从流中获取出来。

*

* 通常该集合用于操作以键值对形式存在的配置文件。

package day22;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.util.Properties;

import java.util.Set;

public class PropertiesDemo {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

//properties集合的基本功能存和取演示

propertiesDemo();

//properties集合和流对象相结合的演示

propertiesDemo2();

//持久化,将集合的数据存储到文件中

propertiesDemo3();

//把文件中的数据读取到集合中。

propertiesDemo4();

//修改文件的配置信息

propertiesDemo5();

}

public static void propertiesDemo() {

//创建一个Properties集合

Properties prop=new Properties();

//存储元素

prop.setProperty("zhangsan", "30");

prop.setProperty("lisi", "32");

prop.setProperty("wangwu", "36");

prop.setProperty("zhaoliu", "20");

//修改元素

prop.setProperty("wangwu", "26");

//取出所有元素

Set<String> names=prop.stringPropertyNames();

for(String name:names){

String value=prop.getProperty(name);

System.out.println(name+":"+value);

}

}

public static void propertiesDemo2() {

Properties prop=new Properties();

prop.setProperty("zhangsan", "30");

prop.setProperty("lisi", "32");

prop.setProperty("wangwu", "36");

prop.setProperty("zhaoliu", "20");

prop.list(System.out);    //list方法,列出集合中的键和值,一般调试时用。

}

public static void propertiesDemo3() throws IOException{

Properties prop=new Properties();

prop.setProperty("zhangsan", "30");

prop.setProperty("lisi", "32");

prop.setProperty("wangwu", "36");

prop.setProperty("zhaoliu", "20");

//  持久化

//需求:集合中的这些字符串键值信息方法一结束就会消失,想要将它们持久化存储到文件中。

//      就要用到store方法,这需要关联输出流,所以创建一个。

FileOutputStream fos=new FileOutputStream("info.txt");

//      将集合数据存储到文件中,使用store方法。

prop.store(fos, "name+age");

fos.close();

}

public static void propertiesDemo4() throws IOException{

Properties prop=new Properties();

//需求:与Demo3相反,这次要把硬盘中的数据读到集合中。

//注意:文件中的数据必须是键值对。

FileInputStream fis=new FileInputStream("info.txt");

//使用load方法。

prop.load(fis);

fis.close();

prop.list(System.out);      //这个list就是验证一下确实读取到集合中了。

}

public static void propertiesDemo5() throws IOException{

/*

* 需求:对已有的配置文件信息进行修改。

* 步骤:先读取这个文件,并将这个文件的键值数据存储到集合中。

*      再通过集合对数据进行修改,最后通过流将修改后的数据存储到文件中。

*/

File file=new File("info.txt");

if(!file.exists()){

file.createNewFile();

}

FileReader fr=new FileReader("info.txt");

Properties prop=new Properties();

prop.load(fr);

prop.setProperty("wangwu", "16");

FileWriter fw=new FileWriter(file);

prop.store(fw, "");

fr.close();

fw.close();

prop.list(System.out);

}

}

properties的一个练习:

package day22;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Properties;

public class PropertiesTest {

/**

* 需求:定义一个功能,获取一个应用程序运行的次数,若超过5次,

* 给出   “使用次数已到,请注册”  的提示,并不要再运行程序。

*

* 思路:1.得有一个计数器,每次程序启动就计数一次,并且是在原有的基础上计数。

* 2.计数器就是一个变量。突然冒出一个想法,程序启动时进行计数,计数器必须存在于内存并进行运算。

*    可是程序一结束,计数器不就消失了吗?再次启动程序,计数器不就重置了嘛,但我们需要多次启动同一个

*    应用程序,启动的是同一个计数器,这就需要计数器的生命周期变长,从内存存储到硬盘文件中。

* 3.如何使用这个计数器呢?

*    首先,程序启动时,应该先读取这个用于记录计数器信息的配置文件,获取上一次计数器次数,

*    其次,对该次数就行自增,并且自增后的次数要重新存储到配置文件中。

* 4.文件中的信息该如何进行存储呢?

*   直接存储次数值可以,但不明确该数据的含义,所以起名字就很重要了。这就有了名字和值得对应,就要用键值对。

*  可是映射关系map搞定,又要读取硬盘上的数据,所以map+IO=Properties。

* @throws IOException

*/

public static void main(String[] args) throws IOException {

getAppCount();

}

public static void getAppCount() throws IOException{

//将配置文件封装成对象

File confile=new File("count.properties.txt");

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){

//System.out.println("使用次数已到,请注册");

//return; //这样写不好,函数结束了,其他程序还在运行。

throw new RuntimeException("使用次数已到,请注册");

}

}

count++;

//将改变后的次数重新存储到集合中

prop.setProperty("time", count+"");

FileOutputStream fos=new FileOutputStream(confile);

prop.store(fos, "");

fos.close();

fis.close();

}

}

练习:

package day22;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileWriter;

import java.io.FilenameFilter;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

public class Test {

/**

* 需求:获取指定目录下,指定扩展名的文件(包含子目录中的),

* 这些文件的绝对路径写入到一个文本文件中。

* 简单说,就是建立一个指定扩展名的文件的列表。

*

* 思路:1.必须进行深度遍历。

* 2.要在遍历的过程中进行过滤。将符合条件的内容都存储到容器中。

* 3.对容器中的内容进行遍历并将绝对路径写入到文件中。

*/

public static void main(String[] args) {

File dir=new File("e://javatest");

FilenameFilter filter=new FilenameFilter(){

@Override

public boolean accept(File dir, String name) {

return name.endsWith(".java");

}

};

List<File> list=new ArrayList<File>();

getFiles(dir,filter,list);

File destFile=new File(dir,"javalist.txt");

writeToFile(list,destFile);

}

public static void getFiles(File dir,FilenameFilter filter,List<File> list){

/*

* 对指定目录的内容进行深度遍历,并按照制定过滤器进行过滤,

* 将过滤后的内容存储到指定容器list中。

*/

File[] files=dir.listFiles();

for(File file:files){

if(file.isDirectory()){

//递归

getFiles(file,filter,list);

}

else{

//对遍历到的文件进行过滤。将符合条件的File对象存储到List集合中

if(filter.accept(dir,file.getName())){

list.add(file);

}

}

}

}

public static void writeToFile(List<File> list,File destFile) {

BufferedWriter bufw=null;

try {

bufw=new BufferedWriter(new FileWriter(destFile));

for(File file:list){

bufw.write(file.getAbsolutePath());

bufw.newLine();

bufw.flush();

}

} catch (IOException e) {

throw new RuntimeException("写入失败");

} finally{

if(bufw!=null)

try {

bufw.close();

} catch (IOException e) {

throw new RuntimeException("关闭失败");

}

}

}

}

IO包中的其他类:

打印流:PrintWriter和PrintStream。可以直接操作输入流和文件。

1.它提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式。

2.它不抛IOException.

3.他的构造函数接收三种类型的值:

a.字符串路径

b.File对象

c.字节输出流

序列流:SequenceInputStream,对多个流进行合并。

练习:文件切割器和文件合并器

package day22;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Properties;

public class splitFileDemo {

/**

* 练习:文件切割器

* @throws IOException

*/

private static final int SIZE = 1024*1024;     //这就是1M。

public static void main(String[] args) throws IOException {

File file=new File("e:\\javatest\\eclipse\\HelloJava\\LoginScreenLoop.mp3");

splitFile(file);

}

public 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("e:\\javatest\\eclipse\\HelloJava\\partfiles");

if(!dir.exists()){

dir.mkdirs();

}

while((len=fis.read(buf))!=-1){

fos=new FileOutputStream(new File(dir,(count++)+".part"));  //碎片文件文件名要注意,类型也别直接就写txt

fos.write(buf,0,len);

fos.close();

}

fos.close();

fis.close();

//将被切割文件的信息保存到prop中。

prop.setProperty("partcount", count+"");

prop.setProperty("filename", file.getName());

//将prop的数据存储到文件中。

fos=new FileOutputStream(new File(dir,count+".properties"));

prop.store(fos, "save file information");

}

}

package day22;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Enumeration;

import java.util.Properties;

public class MergerDemo {

/**

* 文件合并器

*

* 文件切割器切了之后肯定还要合并嘛

* @throws IOException

*/

public static void main(String[] args) throws IOException {

File dir=new File("partfiles");

mergeFile(dir);

}

public static void mergeFile(File dir) throws IOException{

//先拿被切割文件的配置信息。不知道这个文件叫啥,只知道后缀名是.properties。所以要用过滤器

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("碎片文件不符合要求");

}

//将碎片文件和流对象关联并存储到集合中

ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();

for(int x=1;x<=partFiles.length;x++){

al.add(new FileInputStream(new File(dir,x+".part")));

}

//将多个流合并成一个序列流

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();

}

}

IO包中的其他类:

操作基本数据类型:

DataInputStream和DataOutputStream

操作字节数组:

ByteArrayInputStream和ByteArrayOutputStream

操作字符数组:

CharArrayReader和CharArrayWriter

操作字符串:

StringReader和StrinWriter

DataInputStream和DataOutputStream:

package day22;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

public class DataStreamDemo {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

writeData();

readData();

}

public static void readData() throws IOException {

DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));

String str=dis.readUTF();

System.out.println(str);

}

public static void writeData() throws IOException {

DataOutputStream dos=new DataOutputStream(new FileOutputStream("data.txt"));

dos.writeUTF("你好");

dos.close();

}

}

ByteArrayInputStream和ByteArrayOutputStream:

这两个类关闭无效,关闭后还可以调用且不抛异常。因为此类中的方法不调用底层资源,只是在内存中操作一个数组。

package day22;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

public class ByteArrayStream {

/**

* @param args

*/

public static void main(String[] args) {

ByteArrayInputStream bis=new ByteArrayInputStream("abcdefg".getBytes());

ByteArrayOutputStream bos=new ByteArrayOutputStream();

int ch=0;

while((ch=bis.read())!=-1){

bos.write(ch);

}

//bis这里不用关 ,关了也没用。

System.out.println(bos.toString());

}

}

CharArrayReader和CharArrayWriter

StringReader和StrinWriter

这四个和ByteArrayInputStream,ByteArrayOutputStream类似,类比学习即可。

编码表:

ASCII:美国标准信息交换码  用一个字节的7位可以表示。所以0开头的一般是美国码表。

ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位表示。

GB2312:中国的中文编码表

GBK:中国的中文编码表的升级,融合了更多的中文文字符号。

Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,java语言使用就是unicode。

UTF-8:最多用三个字节来表示一个字符。

package day22;

import java.io.IOException;

public class EncodeDemo {

/**

* 字符串--> 字节数组          编码

* 字节数组--> 字符串          解码

* @throws IOException

*

*/

public static void main(String[] args) throws IOException {

String str="你好";

//编码

byte[] buf=str.getBytes("GBK");

//你好对应的编码(GBK):    -60  -29  -70  -61

//你好对应的编码(UTF-8):    -28  -67  -96  -27  -91  -67

printBytes(buf);

//解码

String s1=new String(buf,"GBK");

System.out.println("s1="+s1);

}

public static void printBytes(byte[] buf) {

for(Byte b:buf){

System.out.print(b+"  ");

}

}

}

一个练习:

package day22;

import java.io.IOException;

public class EncodeTest {

/**

* 在java中,字符串“abcd”与字符串“ab你好”的长度是一样的,都是四个字符。

* 但对应的字节数不同,因为一个汉字占两个字节。

* 定义一个方法,按照最大字节数来去子串。

* 如:对于“ab你好”,如果取三个字节,那么子串就是ab与“你”字的半个

* 那么半个就要舍弃。如果取四个字节就是“ab你”,取五个就是“ab你”。

* @throws IOException

*/

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)+"个字节的结果是:"+cutStringByU8Byte(str,x+1));

}

}

//用U8码表做的方法

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++;

else

break;

}

if(count%3==0)

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");

}

//用GBK做的方法

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++;

else

break;

}

if(count%2==0)

return new String(buf,0,len);

else

return new String(buf,0,len-1);

}

}

时间: 2024-10-19 08:50:15

java(十一)IO流的相关文章

java的Io流学习

Java中io流的学习(一)File:https://blog.csdn.net/qq_41061437/article/details/81672859 Java中io流的学习(二)FileInputStream和FileOutputStream:https://blog.csdn.net/qq_41061437/article/details/81742175 Java中io流的学习(三)BuffereInputStream和BuffereOutputStream:https://blog.

java常用IO流数据流小结

  类名 常用方法 说明 输入流 InputStream int read(); 只能读字节流,虽然返回值是int,但只有低8位起作用. DataInputStream Type readType(); 可以读二进制流,可以读byte,short,int,long,double等二进制流. BufferedReader String readLine(); 可以读文本行. 输出流 OutputStream void write(int); 只能写字节流,虽然形参是int,但只有低8为起作用. D

【Java】IO流简单分辨

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827509.html Java的IO流体系十分庞大,并且体系层次稍复杂,很容易记混或记错.在此,我把平时经常用到的几个流类的简易区分以及体系层次整理出来,方便记忆与辨析.本人对IO了解尚浅,文章如有错漏,恳请前辈指正,感激不尽! 字节流体系: 基类:InputStream/outputStream(抽象类,不能new) 子类: 文件IO字节流:FileInputStream/FileoutputStream

JAVA中IO流总结

本文是在学习中的总结,欢迎转载但请注明出处:http://write.blog.csdn.net/postedit/42119261 我想你对JAVA的IO流有所了解,平时使用的也比较的多,但是对于其具体分类和继承体系可能知道的并不多,可能也很少去看相关的API文档,找出其中的关系和各自的应用情形.本文简单对常用的IO流进行分类整理,并简单举例说明其应用.希望本文对你有所帮助. (A)IO流大致分为两种: (1)字节流:对应抽象类为InputStream(输入流)和 OutputStream(输

【JAVA的 IO流之FileInputStream和FileOutputStream】

java的 IO流即输入输出流,流是一组有顺序的,有起点和终点的字节结合,是对数据传输的总称.即数据在两设备间的传输称为流,流的本质是数据传输. IO流可以分为字节流和字符流.给出相应的IO结构图: 在接下来的一段时间里,将会慢慢介绍各种流的使用,本篇博客先介绍字节流的FileOutputStream和相对应的FileInputStream. 一.FileOutputStream(文件输出流) OutputStream是一个抽象类,抽象类必须通过子类实现.现在要向文件里输出就要用FileOutp

java的IO流,字节流和字符流

java操作文件都是通过流来处理的,(其实其他很多语言也是这样) 第一:java的IO流,分为:输入流 和 输出流(这真是废话,这是从流向的角度来说的) 第二:java的所有IO流,只分为:字节流 和 字符流(其实就是传输的颗粒,传输的基本单位) 总结:凡是处理纯文本的优先考虑字符流:其他的才考虑使用字节流

Java之IO流---字节流

1.1 IO流的引入 IO流在很多语言已有体现,诸如C语言的stdio.h,C++中的iostream.Java中的IO流大抵是用于在控制台.磁盘.内存上进行数据的读写操作,完成数据的传递. 我们可以对它进行如下分类: 按处理的数据类型可分为字节流与字符流 按流的流向可分为输入流(in)与输出流(out) 按流的功能可分为节点流(Node)和过滤流(Filter) 本篇侧重于梳理字节流相关的知识,毕竟作为字符流的前辈,它还是非常重要的.下篇继续梳理字符流. 1.2 IO流的继承体系图 大概描述了

Java笔记-IO流的运用

1.InputStream和System.in(Scanner) InputStream 输出流以字节为单位来获取数据,且需要复杂的判断并创建字节数组作为缓冲 另外字节转换为字符时容易出现中文乱码的情况:Scanner Java扫描器类,可以从输入流中读取指定类型的数据或字符串. 对于字符数据的读取,应该使用Scanner扫描器进行封装,然后获取字符串类型的数据 2. out和err out和err是System类的两个static类成员变量: out:主要是输出调试信息的输出流,以黑色显示 e

Java之IO流用法总结

Java的IO流概述:1.I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输.如读/写文件,网络通讯等.2.Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行.3.java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据. IO流的分类:1.按操作数据单位不同分为:字节流(8 bit), 字符流(16 bit).2.按数据流的流向不同分为:输入流,输出流.3.按流的角色的不同分为:节点

Java 之IO流及应用

IO流 IO流概述及FileWriter类的使用 FileReader类使用 缓冲流介绍和使用 IO流相关案例 NO.one IO流概述及FileWriter类使用 1.1 IO流概述及分类 IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入流,输出流 1.2 FileWriter类使用 A:打开帮助文档 B:点击显示,找到索引,看到输入框 C:你要学习什么内容,你就在框框里面输入什么内容 举例:Random D:看包